From 67e590cfebaddc900faf829c43d72cdb4a44e31b Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 27 Jul 2018 14:41:30 -0500 Subject: [PATCH] client: Utilize l_parse_args --- client/adapter.c | 24 +++++------- client/command.c | 70 +++++++++++++++-------------------- client/command.h | 5 ++- client/device.c | 79 ++++++++++++++++------------------------ client/display.c | 47 +++++++++++++++++++----- client/display.h | 3 +- client/known-networks.c | 26 ++++--------- client/network.c | 81 ----------------------------------------- client/network.h | 7 +--- client/properties.c | 22 ----------- client/properties.h | 2 - client/wsc.c | 19 +++++++--- 12 files changed, 134 insertions(+), 251 deletions(-) diff --git a/client/adapter.c b/client/adapter.c index 2f07f3be..b6756c1b 100644 --- a/client/adapter.c +++ b/client/adapter.c @@ -219,7 +219,8 @@ static const struct proxy_interface *get_adapter_proxy_by_name( return proxy; } -static enum cmd_status cmd_list(const char *adapter_name, char *args) +static enum cmd_status cmd_list(const char *adapter_name, + char **argv, int argc) { display_table_header("Adapters", MARGIN "%-*s%-*s%-*s%-*s", 19, "Name", 10, "Powered", 20, "Vendor", 20, "Model"); @@ -231,7 +232,8 @@ static enum cmd_status cmd_list(const char *adapter_name, char *args) return CMD_STATUS_OK; } -static enum cmd_status cmd_show(const char *adapter_name, char *args) +static enum cmd_status cmd_show(const char *adapter_name, + char **argv, int argc) { const struct proxy_interface *proxy = get_adapter_proxy_by_name(adapter_name); @@ -250,29 +252,21 @@ static void property_set_callback(struct l_dbus_message *message, dbus_message_has_error(message); } -static enum cmd_status cmd_set_property(const char *adapter_name, char *args) +static enum cmd_status cmd_set_property(const char *adapter_name, + char **argv, int argc) { - char *name; - char *value_str; const struct proxy_interface *proxy = get_adapter_proxy_by_name(adapter_name); if (!proxy) return CMD_STATUS_INVALID_VALUE; - if (!properties_parse_args(args, &name, &value_str)) + if (argc != 2) return CMD_STATUS_INVALID_ARGS; - if (!proxy_property_set(proxy, name, value_str, - property_set_callback)) { - l_free(name); - l_free(value_str); - + if (!proxy_property_set(proxy, argv[0], argv[1], + property_set_callback)) return CMD_STATUS_INVALID_VALUE; - } - - l_free(name); - l_free(value_str); return CMD_STATUS_OK; } diff --git a/client/command.c b/client/command.c index bbe2b719..4c89c649 100644 --- a/client/command.c +++ b/client/command.c @@ -33,14 +33,16 @@ static struct l_queue *command_families; -static enum cmd_status cmd_version(const char *entity, char *arg) +static enum cmd_status cmd_version(const char *entity, + char **argv, int argc) { display("IWD version %s\n", VERSION); return CMD_STATUS_OK; } -static enum cmd_status cmd_quit(const char *entity, char *arg) +static enum cmd_status cmd_quit(const char *entity, + char **argv, int argc) { display_quit(); @@ -323,13 +325,14 @@ char *command_entity_arg_completion(const char *text, int state, } static void execute_cmd(const char *family, const char *entity, - const struct command *cmd, char *args) + const struct command *cmd, + char **argv, int argc) { enum cmd_status status; - display_refresh_set_cmd(family, entity, cmd, args); + display_refresh_set_cmd(family, entity, cmd, argv, argc); - status = cmd->function(entity, args); + status = cmd->function(entity, argv, argc); if (status != CMD_STATUS_OK) goto error; @@ -365,7 +368,8 @@ error: } static bool match_cmd(const char *family, const char *entity, const char *cmd, - char *args, const struct command *command_list) + char **argv, int argc, + const struct command *command_list) { size_t i; @@ -374,50 +378,40 @@ static bool match_cmd(const char *family, const char *entity, const char *cmd, continue; if (!command_list[i].function) - goto nomatch; + return false; - execute_cmd(family, entity, &command_list[i], args); + execute_cmd(family, entity, &command_list[i], argv, argc); return true; } -nomatch: return false; } -static bool match_cmd_family(const char *cmd_family, char *arg) +static bool match_cmd_family(char **argv, int argc) { const struct l_queue_entry *entry; - const char *arg1; - const char *arg2; + + if (argc < 2) + return false; for (entry = l_queue_get_entries(command_families); entry; entry = entry->next) { const struct command_family *family = entry->data; - if (strcmp(family->name, cmd_family)) + if (strcmp(family->name, argv[0])) continue; - arg1 = strtok_r(NULL, " ", &arg); - if (!arg1) - goto nomatch; - - if (match_cmd(family->name, NULL, arg1, arg, - family->command_list)) - return true; - - arg2 = strtok_r(NULL, " ", &arg); - if (!arg2) - goto nomatch; - - if (!match_cmd(family->name, arg1, arg2, arg, - family->command_list)) - goto nomatch; - - return true; + if (argc >= 3) + return match_cmd(family->name, argv[1], argv[2], + argv + 3, argc - 3, + family->command_list); + else + return match_cmd(family->name, NULL, argv[1], + argv + 2, argc - 2, + family->command_list); } -nomatch: return false; } @@ -447,24 +441,20 @@ static void list_cmd_families(void) } } -void command_process_prompt(char *prompt) +void command_process_prompt(char **argv, int argc) { - const char *cmd; - char *arg = NULL; - - cmd = strtok_r(prompt, " ", &arg); - if (!cmd) + if (argc == 0) return; - if (match_cmd_family(cmd, arg)) + if (match_cmd_family(argv, argc)) return; display_refresh_reset(); - if (match_cmd(NULL, NULL, cmd, arg, command_list)) + if (match_cmd(NULL, NULL, argv[0], argv + 1, argc - 1, command_list)) return; - if (strcmp(cmd, "help")) { + if (strcmp(argv[0], "help")) { display("Invalid command\n"); return; } diff --git a/client/command.h b/client/command.h index 30410706..ee400770 100644 --- a/client/command.h +++ b/client/command.h @@ -34,7 +34,8 @@ struct command { const char *entity; const char *cmd; const char *arg; - enum cmd_status (*function)(const char *entity, char *arg); + enum cmd_status (*function)(const char *entity, + char **argv, int argc); const char *desc; const bool refreshable; command_completion_func_t completion; @@ -54,7 +55,7 @@ char **command_completion(const char *text, int start, int end); char *command_entity_arg_completion(const char *text, int state, const struct command *command_list); -void command_process_prompt(char *prompt); +void command_process_prompt(char **argv, int argc); void command_family_register(const struct command_family *family); void command_family_unregister(const struct command_family *family); diff --git a/client/device.c b/client/device.c index 124e7973..00c046df 100644 --- a/client/device.c +++ b/client/device.c @@ -607,7 +607,8 @@ static const struct proxy_interface *get_device_proxy_by_name( return proxy; } -static enum cmd_status cmd_show(const char *device_name, char *args) +static enum cmd_status cmd_show(const char *device_name, + char **argv, int argc) { const struct proxy_interface *proxy = get_device_proxy_by_name(device_name); @@ -626,7 +627,8 @@ static void check_errors_method_callback(struct l_dbus_message *message, dbus_message_has_error(message); } -static enum cmd_status cmd_scan(const char *device_name, char *args) +static enum cmd_status cmd_scan(const char *device_name, + char **argv, int argc) { const struct proxy_interface *proxy = get_device_proxy_by_name(device_name); @@ -640,7 +642,8 @@ static enum cmd_status cmd_scan(const char *device_name, char *args) return CMD_STATUS_OK; } -static enum cmd_status cmd_disconnect(const char *device_name, char *args) +static enum cmd_status cmd_disconnect(const char *device_name, + char **argv, int argc) { const struct proxy_interface *proxy = get_device_proxy_by_name(device_name); @@ -654,7 +657,8 @@ static enum cmd_status cmd_disconnect(const char *device_name, char *args) return CMD_STATUS_OK; } -static enum cmd_status cmd_get_networks(const char *device_name, char *args) +static enum cmd_status cmd_get_networks(const char *device_name, + char **argv, int argc) { const struct proxy_interface *proxy = get_device_proxy_by_name(device_name); @@ -662,10 +666,10 @@ static enum cmd_status cmd_get_networks(const char *device_name, char *args) if (!proxy) return CMD_STATUS_INVALID_ARGS; - if (!args) + if (!argc) goto proceed; - if (!strcmp(args, RSSI_DBMS)) + if (!strcmp(argv[0], RSSI_DBMS)) display_signal_as_dbms = true; else display_signal_as_dbms = false; @@ -677,7 +681,8 @@ proceed: return CMD_STATUS_OK; } -static enum cmd_status cmd_list(const char *device_name, char *args) +static enum cmd_status cmd_list(const char *device_name, + char **argv, int argc) { display_table_header("Devices", MARGIN "%-*s%-*s%-*s%-*s", 20, "Name", 20, "Address", 15, "State", 10, "Adapter"); @@ -689,36 +694,29 @@ static enum cmd_status cmd_list(const char *device_name, char *args) return CMD_STATUS_OK; } -static enum cmd_status cmd_set_property(const char *device_name, char *args) +static enum cmd_status cmd_set_property(const char *device_name, + char **argv, int argc) { - char *name; - char *value_str; const struct proxy_interface *proxy = get_device_proxy_by_name(device_name); if (!proxy) return CMD_STATUS_INVALID_VALUE; - if (!properties_parse_args(args, &name, &value_str)) + if (argc != 2) return CMD_STATUS_INVALID_ARGS; - if (!proxy_property_set(proxy, name, value_str, - check_errors_method_callback)) { - l_free(name); - l_free(value_str); - + if (!proxy_property_set(proxy, argv[0], argv[1], + check_errors_method_callback)) return CMD_STATUS_INVALID_VALUE; - } - - l_free(name); - l_free(value_str); return CMD_STATUS_OK; } -static enum cmd_status cmd_connect(const char *device_name, char *args) +static enum cmd_status cmd_connect(const char *device_name, + char **argv, int argc) { - struct network_args *network_args; + struct network_args network_args; struct l_queue *match; const struct proxy_interface *network_proxy; const struct proxy_interface *device_proxy = @@ -727,68 +725,53 @@ static enum cmd_status cmd_connect(const char *device_name, char *args) if (!device_proxy) return CMD_STATUS_INVALID_VALUE; - network_args = network_parse_args(args); - - if (!network_args || !network_args->name) { - network_args_destroy(network_args); - + if (argc < 1) return CMD_STATUS_INVALID_ARGS; - } - match = network_match_by_device_and_args(device_proxy, network_args); + network_args.name = argv[0]; + if (argc >= 2) + network_args.type = argv[1]; + match = network_match_by_device_and_args(device_proxy, &network_args); if (!match) { - display("Invalid network name '%s'\n", network_args->name); - network_args_destroy(network_args); - + display("Invalid network name '%s'\n", network_args.name); return CMD_STATUS_INVALID_VALUE; } if (l_queue_length(match) > 1) { - if (!network_args->type) { + if (!network_args.type) { display("Provided network name is ambiguous. " "Please specify security type.\n"); } l_queue_destroy(match, NULL); - network_args_destroy(network_args); return CMD_STATUS_INVALID_VALUE; } network_proxy = l_queue_pop_head(match); - l_queue_destroy(match, NULL); - network_args_destroy(network_args); - network_connect(network_proxy); return CMD_STATUS_OK; } static enum cmd_status cmd_connect_hidden_network(const char *device_name, - char *args) + char **argv, + int argc) { - struct network_args *network_args; const struct proxy_interface *proxy = get_device_proxy_by_name(device_name); if (!proxy) return CMD_STATUS_INVALID_VALUE; - network_args = network_parse_args(args); - - if (!network_args || !network_args->name) { - network_args_destroy(network_args); - + if (argc != 1) return CMD_STATUS_INVALID_ARGS; - } proxy_interface_method_call(proxy, "ConnectHiddenNetwork", "s", check_errors_method_callback, - network_args->name); - - network_args_destroy(network_args); + argv[0]); return CMD_STATUS_OK; } diff --git a/client/display.c b/client/display.c index c294b35b..c0bfa3ad 100644 --- a/client/display.c +++ b/client/display.c @@ -47,7 +47,8 @@ static struct display_refresh { char *family; char *entity; const struct command *cmd; - char *args; + char **argv; + int argc; size_t undo_lines; struct l_queue *redo_entries; bool recording; @@ -135,8 +136,9 @@ void display_refresh_reset(void) display_refresh.cmd = NULL; - l_free(display_refresh.args); - display_refresh.args = NULL; + l_strfreev(display_refresh.argv); + display_refresh.argv = NULL; + display_refresh.argc = 0; display_refresh.undo_lines = 0; display_refresh.recording = false; @@ -145,8 +147,11 @@ void display_refresh_reset(void) } void display_refresh_set_cmd(const char *family, const char *entity, - const struct command *cmd, char *args) + const struct command *cmd, + char **argv, int argc) { + int i; + if (cmd->refreshable) { l_free(display_refresh.family); display_refresh.family = l_strdup(family); @@ -156,8 +161,12 @@ void display_refresh_set_cmd(const char *family, const char *entity, display_refresh.cmd = cmd; - l_free(display_refresh.args); - display_refresh.args = l_strdup(args); + l_strfreev(display_refresh.argv); + display_refresh.argc = argc; + + display_refresh.argv = l_new(char *, argc + 1); + for (i = 0; i < argc; i++) + display_refresh.argv[i] = argv[i]; l_queue_clear(display_refresh.redo_entries, l_free); @@ -168,8 +177,16 @@ void display_refresh_set_cmd(const char *family, const char *entity, } if (display_refresh.family && !strcmp(display_refresh.family, family)) { - char *prompt = - l_strdup_printf(IWD_PROMPT"%s%s%s %s %s\n", + struct l_string *buf = l_string_new(128); + L_AUTO_FREE_VAR(char *, args); + char *prompt; + + for (i = 0; i < argc; i++) + l_string_append_printf(buf, "'%s' ", argv[i]); + + args = l_string_unwrap(buf); + + prompt = l_strdup_printf(IWD_PROMPT"%s%s%s %s %s\n", family ? : "", entity ? " " : "", entity ? : "", cmd->cmd ? : "", args ? : ""); @@ -196,7 +213,8 @@ static void timeout_callback(struct l_timeout *timeout, void *user_data) display_refresh.recording = false; display_refresh.cmd->function(display_refresh.entity, - display_refresh.args); + display_refresh.argv, + display_refresh.argc); } void display_refresh_timeout_set(void) @@ -408,6 +426,9 @@ static void reset_masked_input(void) static void readline_callback(char *prompt) { + char **argv; + int argc; + HIST_ENTRY *previous_prompt; if (!prompt) { @@ -432,7 +453,13 @@ static void readline_callback(char *prompt) add_history(prompt); } - command_process_prompt(prompt); + argv = l_parse_args(prompt, &argc); + if (!argv) { + display("Invalid command\n"); + goto done; + } + + command_process_prompt(argv, argc); done: l_free(prompt); diff --git a/client/display.h b/client/display.h index 791625ee..b8c03fd1 100644 --- a/client/display.h +++ b/client/display.h @@ -42,7 +42,8 @@ void display_command_line(const char *command_family, void display_refresh_timeout_set(void); void display_refresh_reset(void); void display_refresh_set_cmd(const char *family, const char *entity, - const struct command *cmd, char *args); + const struct command *cmd, + char **argv, int argc); void display_enable_cmd_prompt(void); void display_disable_cmd_prompt(void); diff --git a/client/known-networks.c b/client/known-networks.c index 5175dbf2..9a7f2ec9 100644 --- a/client/known-networks.c +++ b/client/known-networks.c @@ -244,7 +244,7 @@ static struct proxy_interface_type known_networks_interface_type = { .ops = &known_networks_ops, }; -static enum cmd_status cmd_list(const char *entity, char *args) +static enum cmd_status cmd_list(const char *entity, char **args, int argc) { struct proxy_interface *proxy = proxy_interface_find(IWD_KNOWN_NETWORKS_INTREFACE, @@ -259,9 +259,8 @@ static enum cmd_status cmd_list(const char *entity, char *args) return CMD_STATUS_OK; } -static enum cmd_status cmd_forget(const char *entity, char *args) +static enum cmd_status cmd_forget(const char *entity, char **argv, int argc) { - struct network_args *network_args; const struct l_queue_entry *entry; struct known_network *network = NULL; struct known_network *net; @@ -274,13 +273,8 @@ static enum cmd_status cmd_forget(const char *entity, char *args) if (!proxy) return CMD_STATUS_FAILED; - network_args = network_parse_args(args); - - if (!network_args || !network_args->name) { - network_args_destroy(network_args); - + if (argc < 1) return CMD_STATUS_INVALID_ARGS; - } known_networks = proxy_interface_get_data(proxy); match = NULL; @@ -289,7 +283,7 @@ static enum cmd_status cmd_forget(const char *entity, char *args) entry = entry->next) { net = entry->data; - if (strcmp(net->name, network_args->name)) + if (strcmp(net->name, argv[0])) continue; if (!match) @@ -299,20 +293,16 @@ static enum cmd_status cmd_forget(const char *entity, char *args) } if (!match) { - display("Invalid network name '%s'\n", network_args->name); - network_args_destroy(network_args); - + display("Invalid network name '%s'\n", argv[0]); return CMD_STATUS_INVALID_VALUE; } if (l_queue_length(match) > 1) { - if (!network_args->type) { + if (argc < 2) { display("Provided network name is ambiguous. " "Please specify security type.\n"); l_queue_destroy(match, NULL); - network_args_destroy(network_args); - return CMD_STATUS_INVALID_VALUE; } @@ -320,7 +310,7 @@ static enum cmd_status cmd_forget(const char *entity, char *args) entry = entry->next) { net = entry->data; - if (!strcmp(net->type, network_args->type)) { + if (!strcmp(net->type, argv[1])) { network = net; break; } @@ -330,11 +320,9 @@ static enum cmd_status cmd_forget(const char *entity, char *args) } l_queue_destroy(match, NULL); - network_args_destroy(network_args); if (!network) { display("No network with specified parameters was found\n"); - return CMD_STATUS_INVALID_VALUE; } diff --git a/client/network.c b/client/network.c index 04e5c93c..dcfbcdff 100644 --- a/client/network.c +++ b/client/network.c @@ -64,87 +64,6 @@ void network_connect(const struct proxy_interface *proxy) check_errors_method_callback); } -static const char *skip_spaces(const char *p) -{ - while (*p == ' ') - p++; - - return p; -} - -struct network_args *network_parse_args(const char *args) -{ - struct network_args *network_args; - char **arg_arr; - size_t quoted_len = 0; - size_t i; - const char *p; - - if (unlikely(!args)) - return NULL; - - if (args[0] == '\0') - return NULL; - - args = skip_spaces(args); - p = args; - - network_args = l_new(struct network_args, 1); - - if (*p == '"') { - for (++p, i = 0; *p; p++) { - i++; - - if (*p != '"') - continue; - - quoted_len = i; - } - - if (!quoted_len) { - p = args; - goto split; - } - - network_args->name = l_strndup(args + 1, quoted_len - 1); - p = args + quoted_len + 1; - p = skip_spaces(p); - } -split: - - arg_arr = l_strsplit(p, ' '); - if (!arg_arr || !arg_arr[0]) - goto done; - - if (quoted_len) { - network_args->type = l_strdup(arg_arr[0]); - } else { - network_args->name = l_strdup(arg_arr[0]); - - i = 1; - - while (arg_arr[i] && *arg_arr[i] == '\0') - i++; - - network_args->type = l_strdup(arg_arr[i]); - } - -done: - l_strfreev(arg_arr); - - return network_args; -} - -void network_args_destroy(struct network_args *network_args) -{ - if (unlikely(!network_args)) - return; - - l_free(network_args->name); - l_free(network_args->type); - l_free(network_args); -} - static const char *get_name(const void *data) { const struct network *network = data; diff --git a/client/network.h b/client/network.h index 0a25d483..4ade8168 100644 --- a/client/network.h +++ b/client/network.h @@ -21,16 +21,13 @@ */ struct network_args { - char *name; - char *type; + const char *name; + const char *type; }; bool network_is_connected(const char *path); void network_connect(const struct proxy_interface *proxy); -struct network_args *network_parse_args(const char *args); -void network_args_destroy(struct network_args *network_args); - char *network_name_completion(const struct proxy_interface *device, const char *text, int state); diff --git a/client/properties.c b/client/properties.c index 02be6216..9595b141 100644 --- a/client/properties.c +++ b/client/properties.c @@ -45,25 +45,3 @@ bool properties_builder_append_on_off_variant( return false; } - -bool properties_parse_args(char *args, char **name, char **value) -{ - char **arg_arr; - - if (!args) - return false; - - arg_arr = l_strsplit(args, ' '); - - if (!arg_arr || !arg_arr[0] || !arg_arr[1]) { - l_strfreev(arg_arr); - return false; - } - - *name = l_strdup(arg_arr[0]); - *value = l_strdup(arg_arr[1]); - - l_strfreev(arg_arr); - - return true; -} diff --git a/client/properties.h b/client/properties.h index 79e50856..8cc1aba2 100644 --- a/client/properties.h +++ b/client/properties.h @@ -34,5 +34,3 @@ static const struct property_value_options properties_on_off_opts[] = { bool properties_builder_append_on_off_variant( struct l_dbus_message_builder *builder, const char *value_str); - -bool properties_parse_args(char *args, char **name, char **value); diff --git a/client/wsc.c b/client/wsc.c index 3d1ad223..7ce28d51 100644 --- a/client/wsc.c +++ b/client/wsc.c @@ -139,7 +139,7 @@ static void display_wsc_inline(const char *margin, const void *data) 20, proxy_interface_get_identity_str(wsc->device)); } -static enum cmd_status cmd_list(const char *device_name, char *args) +static enum cmd_status cmd_list(const char *device_name, char **argv, int argc) { const struct l_queue_entry *entry; struct l_queue *match = @@ -168,7 +168,8 @@ static enum cmd_status cmd_list(const char *device_name, char *args) return CMD_STATUS_OK; } -static enum cmd_status cmd_push_button(const char *device_name, char *args) +static enum cmd_status cmd_push_button(const char *device_name, + char **argv, int argc) { const struct proxy_interface *proxy = device_wsc_get(device_name); @@ -184,7 +185,8 @@ static enum cmd_status cmd_push_button(const char *device_name, char *args) return CMD_STATUS_OK; } -static enum cmd_status cmd_start_user_pin(const char *device_name, char *args) +static enum cmd_status cmd_start_user_pin(const char *device_name, + char **argv, int argc) { const struct proxy_interface *proxy = device_wsc_get(device_name); @@ -194,13 +196,17 @@ static enum cmd_status cmd_start_user_pin(const char *device_name, char *args) return CMD_STATUS_INVALID_VALUE; } + if (argc != 1) + return CMD_STATUS_INVALID_ARGS; + proxy_interface_method_call(proxy, "StartPin", "s", - check_errors_method_callback, args); + check_errors_method_callback, argv[0]); return CMD_STATUS_OK; } -static enum cmd_status cmd_start_pin(const char *device_name, char *args) +static enum cmd_status cmd_start_pin(const char *device_name, + char **argv, int argc) { const struct proxy_interface *proxy = device_wsc_get(device_name); @@ -216,7 +222,8 @@ static enum cmd_status cmd_start_pin(const char *device_name, char *args) return CMD_STATUS_OK; } -static enum cmd_status cmd_cancel(const char *device_name, char *args) +static enum cmd_status cmd_cancel(const char *device_name, + char **argv, int argc) { const struct proxy_interface *proxy = device_wsc_get(device_name);