Browse Source

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>
Jouni Malinen 12 years ago
parent
commit
376204934d
1 changed files with 63 additions and 1 deletions
  1. 63 1
      wpa_supplicant/wpa_cli.c

+ 63 - 1
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(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) {