tizen 2.3 release
[external/buxton.git] / src / cli / main.c
1 /*
2  * This file is part of buxton.
3  *
4  * Copyright (C) 2013 Intel Corporation
5  *
6  * buxton is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1
9  * of the License, or (at your option) any later version.
10  */
11
12 #ifdef HAVE_CONFIG_H
13         #include "config.h"
14 #endif
15
16 /**
17  * \file cli/main.c Buxton command line interface
18  *
19  * Provides a CLI to Buxton through which a variety of operations can be
20  * carried out
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <errno.h>
28 #include <getopt.h>
29
30 #include "buxton.h"
31 #include "backend.h"
32 #include "client.h"
33 #include "configurator.h"
34 #include "direct.h"
35 #include "hashmap.h"
36 #include "protocol.h"
37 #include "util.h"
38
39 static Hashmap *commands;
40 static BuxtonControl control;
41
42 static void print_version(void)
43 {
44         printf("buxtonctl " PACKAGE_VERSION "\n"
45                "Copyright (C) 2013 Intel Corporation\n"
46                "buxton is free software; you can redistribute it and/or modify\n"
47                "it under the terms of the GNU Lesser General Public License as\n"
48                "published by the Free Software Foundation; either version 2.1\n"
49                "of the License, or (at your option) any later version.\n");
50 }
51
52 static bool print_help(void)
53 {
54         const char *key;
55         Iterator iterator;
56         Command *command;
57
58         printf("buxtonctl: Usage\n\n");
59
60         HASHMAP_FOREACH_KEY(command, key, commands, iterator) {
61                 printf("\t%12s - %s\n", key, command->description);
62         };
63
64         return true;
65 }
66
67 static void print_usage(Command *command)
68 {
69         if (command->min_arguments == command->max_arguments) {
70                 printf("%s takes %d arguments - %s\n", command->name, command->min_arguments, command->usage);
71         } else {
72                 printf("%s takes at least %d arguments - %s\n", command->name, command->min_arguments, command->usage);
73         }
74 }
75
76 /**
77  * Entry point into buxtonctl
78  * @param argc Number of arguments passed
79  * @param argv An array of string arguments
80  * @returns EXIT_SUCCESS if the operation succeeded, otherwise EXIT_FAILURE
81  */
82 int main(int argc, char **argv)
83 {
84         bool ret = false;
85         Command c_get_string, c_set_string;
86         Command c_get_int32, c_set_int32;
87         Command c_get_uint32, c_set_uint32;
88         Command c_get_int64, c_set_int64;
89         Command c_get_uint64, c_set_uint64;
90         Command c_get_float, c_set_float;
91         Command c_get_double, c_set_double;
92         Command c_get_bool, c_set_bool;
93         Command c_set_label;
94         Command c_create_group, c_remove_group;
95         Command c_unset_value;
96         Command c_create_db;
97         Command *command;
98         int i = 0;
99         int c;
100         bool help = false;
101         bool version = false;
102         control.client.direct = false;
103         char *conf_path = NULL;
104         BuxtonClient client = NULL;
105
106         /* libtool bites my twinkie */
107         include_configurator();
108         include_protocol();
109         include_serialize();
110
111         /* Build a command list */
112         commands = hashmap_new(string_hash_func, string_compare_func);
113         if (!commands) {
114                 exit(EXIT_FAILURE);
115         }
116
117         /* Strings */
118         c_get_string = (Command) { "get-string", "Get a string value by key",
119                                    2, 3, "[layer] group name", &cli_get_value, STRING };
120         hashmap_put(commands, c_get_string.name, &c_get_string);
121
122         c_set_string = (Command) { "set-string", "Set a key with a string value",
123                                    4, 4, "layer group name value", &cli_set_value, STRING };
124         hashmap_put(commands, c_set_string.name, &c_set_string);
125
126         /* 32bit Integers */
127         c_get_int32 = (Command) { "get-int32", "Get an int32_t value by key",
128                                   2, 3, "[layer] group name", &cli_get_value, INT32 };
129         hashmap_put(commands, c_get_int32.name, &c_get_int32);
130
131         c_set_int32 = (Command) { "set-int32", "Set a key with an int32_t value",
132                                   4, 4, "layer group name value", &cli_set_value, INT32 };
133         hashmap_put(commands, c_set_int32.name, &c_set_int32);
134
135         /* Unsigned 32bit Integers */
136         c_get_uint32 = (Command) { "get-uint32", "Get an uint32_t value by key",
137                                    2, 3, "[layer] group name", &cli_get_value, UINT32 };
138         hashmap_put(commands, c_get_uint32.name, &c_get_uint32);
139
140         c_set_uint32 = (Command) { "set-uint32", "Set a key with an uint32_t value",
141                                    4, 4, "layer group name value", &cli_set_value, UINT32 };
142         hashmap_put(commands, c_set_uint32.name, &c_set_uint32);
143
144         /* 32bit Integers */
145         c_get_int64 = (Command) { "get-int64", "Get an int64_t value by key",
146                                   2, 3, "[layer] group name", &cli_get_value, INT64};
147         hashmap_put(commands, c_get_int64.name, &c_get_int64);
148
149         c_set_int64 = (Command) { "set-int64", "Set a key with an int64_t value",
150                                   4, 4, "layer group name value", &cli_set_value, INT64 };
151         hashmap_put(commands, c_set_int64.name, &c_set_int64);
152
153         /* Unsigned 32bit Integers */
154         c_get_uint64 = (Command) { "get-uint64", "Get an uint64_t value by key",
155                                    2, 3, "[layer] group name", &cli_get_value, UINT64};
156         hashmap_put(commands, c_get_uint64.name, &c_get_uint64);
157
158         c_set_uint64 = (Command) { "set-uint64", "Set a key with an uint64_t value",
159                                    4, 4, "layer group name value", &cli_set_value, UINT64 };
160         hashmap_put(commands, c_set_uint64.name, &c_set_uint64);
161
162         /* Floats */
163         c_get_float = (Command) { "get-float", "Get a float point value by key",
164                                   2, 3, "[layer] group name", &cli_get_value, FLOAT };
165         hashmap_put(commands, c_get_float.name, &c_get_float);
166
167         c_set_float = (Command) { "set-float", "Set a key with a floating point value",
168                                   4, 4, "layer group name value", &cli_set_value, FLOAT };
169         hashmap_put(commands, c_set_float.name, &c_set_float);
170
171         /* Doubles */
172         c_get_double = (Command) { "get-double", "Get a double precision value by key",
173                                    2, 3, "[layer] group name", &cli_get_value, DOUBLE };
174         hashmap_put(commands, c_get_double.name, &c_get_double);
175
176         c_set_double = (Command) { "set-double", "Set a key with a double precision value",
177                                    4, 4, "layer group name value", &cli_set_value, DOUBLE };
178         hashmap_put(commands, c_set_double.name, &c_set_double);
179
180         /* Booleans */
181         c_get_bool = (Command) { "get-bool", "Get a boolean value by key",
182                                  2, 3, "[layer] group name", &cli_get_value, BOOLEAN };
183         hashmap_put(commands, c_get_bool.name, &c_get_bool);
184
185         c_set_bool = (Command) { "set-bool", "Set a key with a boolean value",
186                                  4, 4, "layer group name value", &cli_set_value, BOOLEAN };
187         hashmap_put(commands, c_set_bool.name, &c_set_bool);
188
189         /* SMACK labels */
190         c_set_label = (Command) { "set-label", "Set a value's label",
191                                   3, 4, "layer group [name] label", &cli_set_label, STRING };
192
193         hashmap_put(commands, c_set_label.name, &c_set_label);
194
195         /* Group management */
196         c_create_group = (Command) { "create-group", "Create a group in a layer",
197                                      2, 2, "layer group", &cli_create_group, STRING };
198         hashmap_put(commands, c_create_group.name, &c_create_group);
199
200         c_remove_group = (Command) { "remove-group", "Remove a group from a layer",
201                                      2, 2, "layer group", &cli_remove_group, STRING };
202         hashmap_put(commands, c_remove_group.name, &c_remove_group);
203
204         /* Unset value */
205         c_unset_value = (Command) { "unset-value", "Unset a value by key",
206                                     3, 3, "layer group name", &cli_unset_value, STRING };
207         hashmap_put(commands, c_unset_value.name, &c_unset_value);
208
209         /* Create db for layer */
210         c_create_db = (Command) { "create-db", "Create the database file for a layer",
211                                     1, 1, "layer", &cli_create_db, STRING };
212         hashmap_put(commands, c_create_db.name, &c_create_db);
213
214         static struct option opts[] = {
215                 { "config-file", 1, NULL, 'c' },
216                 { "direct",      0, NULL, 'd' },
217                 { "help",        0, NULL, 'h' },
218                 { "version", 0, NULL, 'v' },
219                 { NULL, 0, NULL, 0 }
220         };
221
222         while (true) {
223                 c = getopt_long(argc, argv, "c:dvh", opts, &i);
224
225                 if (c == -1) {
226                         break;
227                 }
228
229                 switch (c) {
230                 case 'c':
231                         conf_path = strdup(optarg);
232                         if (!conf_path) {
233                                 goto end;
234                         }
235                         break;
236                 case 'd':
237                         control.client.direct = true;
238                         break;
239                 case 'v':
240                         version = true;
241                         break;
242                 case 'h':
243                         help = true;
244                         break;
245                 }
246         }
247
248         if (version) {
249                 print_version();
250                 goto end;
251         }
252
253         if (optind == argc) {
254                 print_help();
255                 goto end;
256         }
257
258         if ((command = hashmap_get(commands, argv[optind])) == NULL) {
259                 printf("Unknown command: %s\n", argv[optind]);
260                 goto end;
261         }
262
263         /* We now execute the command */
264         if (command->method == NULL) {
265                 printf("Not yet implemented: %s\n", command->name);
266                 goto end;
267         }
268
269         if (help) {
270                 /* Ensure we cleanup and abort when using help */
271                 print_usage(command);
272                 ret = false;
273                 goto end;
274         }
275
276         if ((argc - optind - 1 < command->min_arguments) ||
277             (argc - optind - 1 > command->max_arguments)) {
278                 print_usage(command);
279                 print_help();
280                 ret = false;
281                 goto end;
282         }
283
284         control.client.uid = geteuid();
285         if (!control.client.direct) {
286                 if (conf_path) {
287                         if (buxton_set_conf_file(conf_path)) {
288                                 printf("Failed to set configuration file path\n");
289                         }
290                 }
291                 if (buxton_open(&client) < 0) {
292                         control.client.direct = true;
293                 } else {
294                         control.client = *(_BuxtonClient *)client;
295                 }
296         }
297
298         if (control.client.direct) {
299                 if (conf_path) {
300                         int r;
301                         struct stat st;
302
303                         r = stat(conf_path, &st);
304                         if (r == -1) {
305                                 printf("Invalid configuration file path\n");
306                                 goto end;
307                         } else {
308                                 if (st.st_mode & S_IFDIR) {
309                                         printf("Configuration file given is a directory\n");
310                                         goto end;
311                                 }
312                         }
313                         buxton_add_cmd_line(CONFIG_CONF_FILE, conf_path);
314                 }
315                 if (!buxton_direct_open(&(control))) {
316                         printf("Failed to directly talk to Buxton\n");
317                         ret = false;
318                         goto end;
319                 }
320         }
321
322         /* Connected to buxton_client, execute method */
323         ret = command->method(&control, command->type,
324                               optind + 1 < argc ? argv[optind + 1] : NULL,
325                               optind + 2 < argc ? argv[optind + 2] : NULL,
326                               optind + 3 < argc ? argv[optind + 3] : NULL,
327                               optind + 4 < argc ? argv[optind + 4] : NULL);
328
329 end:
330         free(conf_path);
331         hashmap_free(commands);
332         if (control.client.direct) {
333                 buxton_direct_close(&control);
334         } else {
335                 if (client) {
336                         buxton_close(client);
337                 }
338         }
339
340         if (ret) {
341                 return EXIT_SUCCESS;
342         }
343         return EXIT_FAILURE;
344 }
345
346 /*
347  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
348  *
349  * Local variables:
350  * c-basic-offset: 8
351  * tab-width: 8
352  * indent-tabs-mode: t
353  * End:
354  *
355  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
356  * :indentSize=8:tabSize=8:noTabs=false:
357  */