client: Trim off spaces from user input
[platform/upstream/connman.git] / client / input.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2012-2013  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <glib.h>
31 #include <readline/readline.h>
32 #include <readline/history.h>
33
34 #include <gdbus.h>
35 #include "input.h"
36 #include "commands.h"
37
38 static DBusConnection *connection;
39 static GMainLoop *main_loop;
40 static bool interactive = false;
41
42 static bool save_input;
43 static char *saved_line;
44 static int saved_point;
45
46 void __connmanctl_quit(void)
47 {
48         if (main_loop != NULL)
49                 g_main_loop_quit(main_loop);
50 }
51
52 bool __connmanctl_is_interactive(void)
53 {
54         return interactive;
55 }
56
57 void __connmanctl_save_rl(void)
58 {
59         if (interactive == false)
60                 return;
61
62         save_input = !RL_ISSTATE(RL_STATE_DONE);
63
64         if (save_input) {
65                 saved_point = rl_point;
66                 saved_line = rl_copy_text(0, rl_end);
67                 rl_save_prompt();
68                 rl_replace_line("", 0);
69                 rl_redisplay();
70         }
71 }
72
73 void __connmanctl_redraw_rl(void)
74 {
75         if (interactive == false)
76                 return;
77
78         if (save_input) {
79                 rl_restore_prompt();
80                 rl_replace_line(saved_line, 0);
81                 rl_point = saved_point;
82                 rl_redisplay();
83                 free(saved_line);
84         }
85
86         save_input = 0;
87 }
88
89 static void rl_handler(char *input)
90 {
91         char **args, **trim_args;
92         int num, len, err, i;
93
94         if (input == NULL) {
95                 rl_newline(1, '\n');
96                 g_main_loop_quit(main_loop);
97                 return;
98         }
99
100         args = g_strsplit(input, " ", 0);
101         num = g_strv_length(args);
102
103         trim_args = g_new0(char *, num);
104         for (i = 0, len = 0; i < num; i++) {
105                 if (*args[i] != '\0') {
106                         trim_args[len] = args[i];
107                         len++;
108                 }
109         }
110
111         if (len > 0) {
112
113                 add_history(input);
114
115                 err = __connmanctl_commands(connection, trim_args, len);
116
117                 if (err > 0)
118                         g_main_loop_quit(main_loop);
119         }
120
121         g_strfreev(args);
122         g_free(trim_args);
123 }
124
125 static gboolean input_handler(GIOChannel *channel, GIOCondition condition,
126                 gpointer user_data)
127 {
128         if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
129                 g_main_loop_quit(main_loop);
130                 return FALSE;
131         }
132
133         rl_callback_read_char();
134         return TRUE;
135 }
136
137 static char **complete_command(const char *text, int start, int end)
138 {
139         char **command = NULL;
140
141         rl_attempted_completion_over = 1;
142
143         if (start == 0)
144                 command = rl_completion_matches(text,
145                                 __connmanctl_lookup_command);
146
147         return command;
148 }
149
150 int __connmanctl_input_init(int argc, char *argv[])
151 {
152         char *help[] = {
153                 "help",
154                 NULL
155         };
156         guint source = 0;
157         int err;
158         DBusError dbus_err;
159
160         dbus_error_init(&dbus_err);
161         connection = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, &dbus_err);
162
163         if (dbus_error_is_set(&dbus_err)) {
164                 fprintf(stderr, "Error: %s\n", dbus_err.message);
165                 dbus_error_free(&dbus_err);
166                 return 1;
167         }
168
169         if (argc < 2) {
170                 GIOChannel *channel;
171
172                 interactive = true;
173
174                 channel = g_io_channel_unix_new(fileno(stdin));
175                 source = g_io_add_watch(channel,
176                                 G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
177                                 input_handler, NULL);
178                 g_io_channel_unref(channel);
179
180                 rl_callback_handler_install("connmanctl> ", rl_handler);
181                 rl_attempted_completion_function = complete_command;
182                 err = -EINPROGRESS;
183
184         } else {
185                 interactive = false;
186
187                 if (strcmp(argv[1], "--help") == 0 ||
188                                 strcmp(argv[1], "-h") == 0)
189                         err = __connmanctl_commands(connection, help, 1);
190                 else
191                         err = __connmanctl_commands(connection, argv + 1,
192                                         argc -1);
193         }
194
195         if (err == -EINPROGRESS) {
196                 main_loop = g_main_loop_new(NULL, FALSE);
197                 g_main_loop_run(main_loop);
198
199                 if (source > 0)
200                         g_source_remove(source);
201
202                 err = 0;
203         }
204
205         if (interactive == true) {
206                 rl_callback_handler_remove();
207                 rl_message("");
208         }
209
210         dbus_connection_unref(connection);
211         if (main_loop != NULL)
212                 g_main_loop_unref(main_loop);
213
214         if (err < 0)
215                 err = -err;
216         else
217                 err = 0;
218
219         return err;
220 }