From 376204934db44d45f798bdde4db005bc88d666f0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 23 May 2013 20:35:02 +0300 Subject: [PATCH] wpa_cli: Support tab completion with ifname= prefix Enable tab completion for the cases where ifname= prefix is used in interactive mode by skipping over that prefix before running through the per-command completion routines. The ifname= prefix itself is also covered by adding the possible interface names to the command list. Signed-hostap: Jouni Malinen --- wpa_supplicant/wpa_cli.c | 64 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 20b699cf4..5e6643fcd 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -91,6 +91,7 @@ struct cli_txt_entry { static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */ static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */ static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */ +static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */ static void print_help(const char *cmd); @@ -2832,9 +2833,12 @@ static char ** wpa_list_cmd_list(void) { char **res; int i, count; + struct cli_txt_entry *e; count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]); - res = os_calloc(count, sizeof(char *)); + count += dl_list_len(&p2p_groups); + count += dl_list_len(&ifnames); + res = os_calloc(count + 1, sizeof(char *)); if (res == NULL) return NULL; @@ -2844,6 +2848,22 @@ static char ** wpa_list_cmd_list(void) break; } + dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) { + size_t len = 8 + os_strlen(e->txt); + res[i] = os_malloc(len); + if (res[i] == NULL) + break; + os_snprintf(res[i], len, "ifname=%s", e->txt); + i++; + } + + dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) { + res[i] = os_strdup(e->txt); + if (res[i] == NULL) + break; + i++; + } + return res; } @@ -2875,6 +2895,14 @@ static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos) const char *end; char *cmd; + if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) { + end = os_strchr(str, ' '); + if (end && pos > end - str) { + pos -= end - str + 1; + str = end + 1; + } + } + end = os_strchr(str, ' '); if (end == NULL || str + pos < end) return wpa_list_cmd_list(); @@ -3347,6 +3375,38 @@ static void update_bssid_list(struct wpa_ctrl *ctrl) } +static void update_ifnames(struct wpa_ctrl *ctrl) +{ + char buf[4096]; + size_t len = sizeof(buf); + int ret; + char *cmd = "INTERFACES"; + char *pos, *end; + char txt[200]; + + cli_txt_list_flush(&ifnames); + + if (ctrl == NULL) + return; + ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL); + if (ret < 0) + return; + buf[len] = '\0'; + + pos = buf; + while (pos) { + end = os_strchr(pos, '\n'); + if (end == NULL) + break; + *end = '\0'; + ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos); + if (ret > 0 && ret < (int) sizeof(txt)) + cli_txt_list_add(&ifnames, txt); + pos = end + 1; + } +} + + static void try_connection(void *eloop_ctx, void *timeout_ctx) { if (ctrl_conn) @@ -3386,6 +3446,7 @@ static void wpa_cli_interactive(void) cli_txt_list_flush(&p2p_peers); cli_txt_list_flush(&p2p_groups); cli_txt_list_flush(&bsses); + cli_txt_list_flush(&ifnames); if (edit_started) edit_deinit(hfile, wpa_cli_edit_filter_history_cb); os_free(hfile); @@ -3588,6 +3649,7 @@ int main(int argc, char *argv[]) } if (interactive) { + update_ifnames(ctrl_conn); mon_conn = wpa_ctrl_open(global); if (mon_conn) { if (wpa_ctrl_attach(mon_conn) == 0) {