summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrik Flykt <patrik.flykt@linux.intel.com>2013-03-27 13:53:49 +0200
committerPatrik Flykt <patrik.flykt@linux.intel.com>2013-04-04 10:22:13 +0300
commit3ff40ccff44a46e735189b528abd73a3ff7a0511 (patch)
tree18686c3c705fa7e47271f574967d849f2dd3b091
parent4f21d25e38219c3b909674327d66c2d6219e99c2 (diff)
downloadconnman-3ff40ccff44a46e735189b528abd73a3ff7a0511.tar.gz
connman-3ff40ccff44a46e735189b528abd73a3ff7a0511.tar.bz2
connman-3ff40ccff44a46e735189b528abd73a3ff7a0511.zip
client: Add input handling
Set up readline command line input handling. Add helper functions to save and redraw the command line when output needs to be printed to the screen.
-rw-r--r--Makefile.am3
-rw-r--r--client/commands.h25
-rw-r--r--client/input.c184
-rw-r--r--client/input.h42
4 files changed, 253 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 21b7070b..5e8eefe8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -236,7 +236,8 @@ client_connmanctl_SOURCES = $(gdbus_sources) src/connman.h \
client/technology.h client/technology.c \
client/interactive.h client/interactive.c \
client/monitor.h client/monitor.c \
- client/commands.c client/main.c
+ client/commands.h client/commands.c client/main.c \
+ client/input.h client/input.c
client_connmanctl_LDADD = @DBUS_LIBS@ @GLIB_LIBS@ -lreadline -ldl
endif
diff --git a/client/commands.h b/client/commands.h
new file mode 100644
index 00000000..b3536a6c
--- /dev/null
+++ b/client/commands.h
@@ -0,0 +1,25 @@
+/*
+ *
+ * Connection Manager
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <dbus/dbus.h>
+
+int commands(DBusConnection *connection, char *argv[], int argc);
diff --git a/client/input.c b/client/input.c
new file mode 100644
index 00000000..1a313fc7
--- /dev/null
+++ b/client/input.c
@@ -0,0 +1,184 @@
+/*
+ *
+ * Connection Manager
+ *
+ * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <glib.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include <gdbus.h>
+#include "input.h"
+#include "commands.h"
+
+static DBusConnection *connection;
+static GMainLoop *main_loop;
+static bool interactive = false;
+
+static bool save_input;
+static char *saved_line;
+static int saved_point;
+
+void __connmanctl_quit(void)
+{
+ if (main_loop != NULL)
+ g_main_loop_quit(main_loop);
+}
+
+bool __connmanctl_is_interactive(void)
+{
+ return interactive;
+}
+
+void __connmanctl_save_rl(void)
+{
+ if (interactive == false)
+ return;
+
+ save_input = !RL_ISSTATE(RL_STATE_DONE);
+
+ if (save_input) {
+ saved_point = rl_point;
+ saved_line = rl_copy_text(0, rl_end);
+ rl_save_prompt();
+ rl_replace_line("", 0);
+ rl_redisplay();
+ }
+}
+
+void __connmanctl_redraw_rl(void)
+{
+ if (interactive == false)
+ return;
+
+ if (save_input) {
+ rl_restore_prompt();
+ rl_replace_line(saved_line, 0);
+ rl_point = saved_point;
+ rl_redisplay();
+ free(saved_line);
+ }
+
+ save_input = 0;
+}
+
+static void rl_handler(char *input)
+{
+ char **args;
+ int num, err;
+
+ if (input == NULL) {
+ rl_newline(1, '\n');
+ g_main_loop_quit(main_loop);
+ return;
+ }
+ if (*input != '\0')
+ add_history(input);
+
+ args = g_strsplit(input, " ", 0);
+ num = g_strv_length(args);
+
+ err = commands(connection, args, num);
+
+ g_strfreev(args);
+
+ if (err > 0)
+ g_main_loop_quit(main_loop);
+}
+
+static gboolean input_handler(GIOChannel *channel, GIOCondition condition,
+ gpointer user_data)
+{
+ if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
+ g_main_loop_quit(main_loop);
+ return FALSE;
+ }
+
+ rl_callback_read_char();
+ return TRUE;
+}
+
+int __connmanctl_input_init(int argc, char *argv[])
+{
+ guint source = 0;
+ int err;
+ DBusError dbus_err;
+
+ dbus_error_init(&dbus_err);
+ connection = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, &dbus_err);
+
+ if (dbus_error_is_set(&dbus_err)) {
+ fprintf(stderr, "Error: %s\n", dbus_err.message);
+ dbus_error_free(&dbus_err);
+ return 1;
+ }
+
+ if (argc < 2) {
+ GIOChannel *channel;
+
+ interactive = true;
+
+ channel = g_io_channel_unix_new(fileno(stdin));
+ source = g_io_add_watch(channel,
+ G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
+ input_handler, NULL);
+ g_io_channel_unref(channel);
+
+ rl_callback_handler_install("connmanctl> ", rl_handler);
+ err = -EINPROGRESS;
+
+ } else {
+ interactive = false;
+ err = commands(connection, argv + 1, argc -1);
+ }
+
+ if (err == -EINPROGRESS) {
+ main_loop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(main_loop);
+
+ if (source > 0)
+ g_source_remove(source);
+
+ err = 0;
+ }
+
+ if (interactive == true) {
+ rl_callback_handler_remove();
+ rl_message("");
+ }
+
+ dbus_connection_unref(connection);
+ if (main_loop != NULL)
+ g_main_loop_unref(main_loop);
+
+ if (err < 0)
+ err = -err;
+ else
+ err = 0;
+
+ return err;
+}
diff --git a/client/input.h b/client/input.h
new file mode 100644
index 00000000..efab40f1
--- /dev/null
+++ b/client/input.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * Connection Manager
+ *
+ * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __CONNMANCTL_INPUT_H
+#define __CONNMANCTL_INPUT_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void __connmanctl_quit(void);
+bool __connmanctl_is_interactive(void);
+void __connmanctl_save_rl(void);
+void __connmanctl_redraw_rl(void);
+int __connmanctl_input_init(int argc, char *argv[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONNMANCTL_INPUT_H */