[Asterisk-code-review] CLI: Fix composite completion generators. (asterisk[master])

Corey Farrell asteriskteam at digium.com
Wed Dec 13 10:25:38 CST 2017


Corey Farrell has uploaded this change for review. ( https://gerrit.asterisk.org/7558


Change subject: CLI: Fix composite completion generators.
......................................................................

CLI: Fix composite completion generators.

In cases where a parameter can be "all" or a list of channels we assume
that "all" will always match when generating the list of channels.

This issue is resolved by adding support for ast_cli_complete and
ast_complete_channels to use ast_cli_completion_add instead of returning
values.  Both functions switch modes when they are given -1 instead of
a->n.  Now adding "all" and adding the list of channels are two
independent operations.

ASTERISK-21038

Change-Id: Iebef61424689569338d0916ff2e37df944ac76fa
---
M channels/chan_iax2.c
M channels/chan_sip.c
M channels/chan_skinny.c
M include/asterisk/cli.h
M main/bridge.c
M main/cli.c
6 files changed, 49 insertions(+), 42 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/58/7558/1

diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 69261f3..1e2ffaf 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -3636,7 +3636,6 @@
 	struct iax2_peer *peer = NULL;
 	struct iax2_user *user = NULL;
 	static const char * const choices[] = { "all", NULL };
-	char *cmplt;
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -3647,10 +3646,8 @@
 		return NULL;
 	case CLI_GENERATE:
 		if (a->pos == 3) {
-			cmplt = ast_cli_complete(a->word, choices, a->n);
-			if (!cmplt)
-				cmplt = complete_iax2_peers(a->line, a->word, a->pos, a->n - sizeof(choices), IAX_RTCACHEFRIENDS);
-			return cmplt;
+			ast_cli_complete(a->word, choices, -1);
+			return complete_iax2_peers(a->line, a->word, a->pos, a->n, IAX_RTCACHEFRIENDS);
 		}
 		return NULL;
 	}
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index f5cf8ca..fa2599c 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -20610,7 +20610,6 @@
 	int havepattern = 0;
 	struct ao2_iterator i;
 	static const char * const choices[] = { "all", "like", NULL };
-	char *cmplt;
 
 	if (cmd == CLI_INIT) {
 		e->command = "sip prune realtime [peer|all]";
@@ -20621,10 +20620,9 @@
 		return NULL;
 	} else if (cmd == CLI_GENERATE) {
 		if (a->pos == 4 && !strcasecmp(a->argv[3], "peer")) {
-			cmplt = ast_cli_complete(a->word, choices, a->n);
-			if (!cmplt)
-				cmplt = complete_sip_peer(a->word, a->n - sizeof(choices), SIP_PAGE2_RTCACHEFRIENDS);
-			return cmplt;
+			ast_cli_complete(a->word, choices, -1);
+
+			return complete_sip_peer(a->word, a->n, SIP_PAGE2_RTCACHEFRIENDS);
 		}
 		if (a->pos == 5 && !strcasecmp(a->argv[4], "like"))
 			return complete_sip_peer(a->word, a->n, SIP_PAGE2_RTCACHEFRIENDS);
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 6f4231a..3b27f5e 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -3923,11 +3923,8 @@
 {
 	if (pos == 2) {
 		static const char * const completions[] = { "all", NULL };
-		char *ret = ast_cli_complete(word, completions, state);
-		if (!ret) {
-			ret = complete_skinny_devices(word, state - 1);
-		}
-		return ret;
+		ast_cli_complete(word, completions, -1);
+		return complete_skinny_devices(word, state);
 	} else if (pos == 3) {
 		static const char * const completions[] = { "restart", NULL };
 		return ast_cli_complete(word, completions, state);
diff --git a/include/asterisk/cli.h b/include/asterisk/cli.h
index 30c5dc7..eb1749a 100644
--- a/include/asterisk/cli.h
+++ b/include/asterisk/cli.h
@@ -201,6 +201,10 @@
  * Helper function to generate cli entries from a NULL-terminated array.
  * Returns the n-th matching entry from the array, or NULL if not found.
  * Can be used to implement generate() for static entries as below
+ *
+ * If 'pos' is less than 0 this function will always return NULL after all
+ * matching channels are added with ast_cli_completion_add.
+ *
  * (in this example we complete the word in position 2):
   \code
     char *my_generate(const char *line, const char *word, int pos, int n)
@@ -357,6 +361,9 @@
  * complete from the list of active channels.  'rpos' is the required
  * position in the command.  This function will return NULL immediately if
  * 'rpos' is not the same as the current position, 'pos'.
+ *
+ * If 'state' is less than 0 this function will always return NULL after all
+ * matching channels are added with ast_cli_completion_add.
  */
 char *ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos);
 
diff --git a/main/bridge.c b/main/bridge.c
index 5d9c0c1..fbb6465 100644
--- a/main/bridge.c
+++ b/main/bridge.c
@@ -5243,7 +5243,6 @@
 static char *handle_bridge_kick_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	static const char * const completions[] = { "all", NULL };
-	char *complete;
 	struct ast_bridge *bridge;
 
 	switch (cmd) {
@@ -5260,11 +5259,9 @@
 			return complete_bridge_live(a->word, a->n);
 		}
 		if (a->pos == 3) {
-			complete = ast_cli_complete(a->word, completions, a->n);
-			if (!complete) {
-				complete = complete_bridge_participant(a->argv[2], a->line, a->word, a->pos, a->n - 1);
-			}
-			return complete;
+			ast_cli_complete(a->word, completions, -1);
+
+			return complete_bridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
 		}
 		return NULL;
 	}
diff --git a/main/cli.c b/main/cli.c
index 75846b8..d3792a3 100644
--- a/main/cli.c
+++ b/main/cli.c
@@ -913,9 +913,12 @@
 		return NULL;
 
 	case CLI_GENERATE:
-		if (a->pos != e->args)
+		if (a->pos != e->args) {
 			return NULL;
-		return ast_cli_complete(a->word, completions, a->n);
+		}
+		ast_cli_complete(a->word, completions, -1);
+
+		return NULL;
 	}
 
 	/* regular handler */
@@ -1088,7 +1091,6 @@
 {
 	struct ast_channel *c = NULL;
 	static const char * const completions[] = { "all", NULL };
-	char *complete;
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -1104,11 +1106,10 @@
 		if (a->pos != e->args) {
 			return NULL;
 		}
-		complete = ast_cli_complete(a->word, completions, a->n);
-		if (!complete) {
-			complete = ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
-		}
-		return complete;
+		ast_cli_complete(a->word, completions, -1);
+		ast_complete_channels(a->line, a->word, a->pos, -1, e->args);
+
+		return NULL;
 	}
 
 	if (a->argc != 4) {
@@ -1383,14 +1384,13 @@
 		return NULL;
 	case CLI_GENERATE:
 		if (a->pos == 4) {
-			char *complete = ast_cli_complete(a->word, completions_all, a->n);
-			if (!complete) {
-				complete = ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
-			}
-			return complete;
+			ast_cli_complete(a->word, completions_all, -1);
+			ast_complete_channels(a->line, a->word, a->pos, -1, e->args);
 		} else if (a->pos == 5) {
-			return ast_cli_complete(a->word, completions_off, a->n);
+			ast_cli_complete(a->word, completions_off, -1);
 		}
+
+		return NULL;
 	}
 
 	if (cmd == (CLI_HANDLER + 1000)) {
@@ -1482,7 +1482,9 @@
 			"       Shows lots of information about the specified channel.\n";
 		return NULL;
 	case CLI_GENERATE:
-		return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
+		ast_complete_channels(a->line, a->word, a->pos, a->n, -1);
+
+		return NULL;
 	}
 
 	if (a->argc != 4) {
@@ -1650,8 +1652,13 @@
 	len = ast_strlen_zero(word) ? 0 : strlen(word);
 
 	for (i = 0; choices[i]; i++) {
-		if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state)
-			return ast_strdup(choices[i]);
+		if ((!len || !strncasecmp(word, choices[i], len))) {
+			if (state < 0) {
+				ast_cli_completion_add(ast_strdup(choices[i]));
+			} else if (++which > state) {
+				return ast_strdup(choices[i]);
+			}
+		}
 	}
 	return NULL;
 }
@@ -1676,10 +1683,14 @@
 	for (; (msg = ao2_iterator_next(&iter)); ao2_ref(msg, -1)) {
 		struct ast_channel_snapshot *snapshot = stasis_message_data(msg);
 
-		if (!strncasecmp(word, snapshot->name, wordlen) && (++which > state)) {
-			ret = ast_strdup(snapshot->name);
-			ao2_ref(msg, -1);
-			break;
+		if (!strncasecmp(word, snapshot->name, wordlen)) {
+			if (state < 0) {
+				ast_cli_completion_add(ast_strdup(snapshot->name));
+			} else if (++which > state) {
+				ret = ast_strdup(snapshot->name);
+				ao2_ref(msg, -1);
+				break;
+			}
 		}
 	}
 	ao2_iterator_destroy(&iter);

-- 
To view, visit https://gerrit.asterisk.org/7558
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iebef61424689569338d0916ff2e37df944ac76fa
Gerrit-Change-Number: 7558
Gerrit-PatchSet: 1
Gerrit-Owner: Corey Farrell <git at cfware.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20171213/0abefbfd/attachment.html>


More information about the asterisk-code-review mailing list