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 <j@w1.fi>
This commit is contained in:
Jouni Malinen 2013-05-23 20:35:02 +03:00
parent 13b11ba702
commit 376204934d

View file

@ -91,6 +91,7 @@ struct cli_txt_entry {
static DEFINE_DL_LIST(bsses); /* 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_peers); /* struct cli_txt_entry */
static DEFINE_DL_LIST(p2p_groups); /* 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); static void print_help(const char *cmd);
@ -2832,9 +2833,12 @@ static char ** wpa_list_cmd_list(void)
{ {
char **res; char **res;
int i, count; int i, count;
struct cli_txt_entry *e;
count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]); 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) if (res == NULL)
return NULL; return NULL;
@ -2844,6 +2848,22 @@ static char ** wpa_list_cmd_list(void)
break; 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; return res;
} }
@ -2875,6 +2895,14 @@ static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
const char *end; const char *end;
char *cmd; 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, ' '); end = os_strchr(str, ' ');
if (end == NULL || str + pos < end) if (end == NULL || str + pos < end)
return wpa_list_cmd_list(); 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) static void try_connection(void *eloop_ctx, void *timeout_ctx)
{ {
if (ctrl_conn) if (ctrl_conn)
@ -3386,6 +3446,7 @@ static void wpa_cli_interactive(void)
cli_txt_list_flush(&p2p_peers); cli_txt_list_flush(&p2p_peers);
cli_txt_list_flush(&p2p_groups); cli_txt_list_flush(&p2p_groups);
cli_txt_list_flush(&bsses); cli_txt_list_flush(&bsses);
cli_txt_list_flush(&ifnames);
if (edit_started) if (edit_started)
edit_deinit(hfile, wpa_cli_edit_filter_history_cb); edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
os_free(hfile); os_free(hfile);
@ -3588,6 +3649,7 @@ int main(int argc, char *argv[])
} }
if (interactive) { if (interactive) {
update_ifnames(ctrl_conn);
mon_conn = wpa_ctrl_open(global); mon_conn = wpa_ctrl_open(global);
if (mon_conn) { if (mon_conn) {
if (wpa_ctrl_attach(mon_conn) == 0) { if (wpa_ctrl_attach(mon_conn) == 0) {