diff options
author | Patrik Flykt <patrik.flykt@linux.intel.com> | 2013-03-27 13:53:49 +0200 |
---|---|---|
committer | Patrik Flykt <patrik.flykt@linux.intel.com> | 2013-04-04 10:22:13 +0300 |
commit | 3ff40ccff44a46e735189b528abd73a3ff7a0511 (patch) | |
tree | 18686c3c705fa7e47271f574967d849f2dd3b091 | |
parent | 4f21d25e38219c3b909674327d66c2d6219e99c2 (diff) | |
download | connman-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.am | 3 | ||||
-rw-r--r-- | client/commands.h | 25 | ||||
-rw-r--r-- | client/input.c | 184 | ||||
-rw-r--r-- | client/input.h | 42 |
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 */ |