Merge "show applications" from corydon76 (bug #2291)
authorMark Spencer <markster@digium.com>
Fri, 27 Aug 2004 04:21:09 +0000 (04:21 +0000)
committerMark Spencer <markster@digium.com>
Fri, 27 Aug 2004 04:21:09 +0000 (04:21 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3665 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/utils.h
pbx.c
utils.c

index 93f9943..bfbdd95 100755 (executable)
@@ -41,6 +41,7 @@ extern int ast_utils_init(void);
 
 #ifdef LINUX
 #define ast_pthread_create pthread_create
+#define ast_strcasestr strcasestr
 #else
 /* Linux threads have a default 2MB stack size. */
 #ifndef PTHREAD_ATTR_STACKSIZE
@@ -49,4 +50,6 @@ extern int ast_utils_init(void);
 extern int ast_pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data);
 #endif /* LINUX */
 
+extern char *ast_strcasestr(const char *, const char *);
+
 #endif
diff --git a/pbx.c b/pbx.c
index bedcabe..e73eded 100755 (executable)
--- a/pbx.c
+++ b/pbx.c
@@ -2391,8 +2391,10 @@ static char show_application_help[] =
 "       Describes a particular application.\n";
 
 static char show_applications_help[] =
-"Usage: show applications\n"
-"       List applications which are currently available.\n";
+"Usage: show applications [{like|describing} <text>]\n"
+"       List applications which are currently available.\n"
+"       If 'like', <text> will be a substring of the app name\n"
+"       If 'describing', <text> will be a substring of the description\n";
 
 static char show_dialplan_help[] =
 "Usage: show dialplan [exten@][context]\n"
@@ -2553,6 +2555,7 @@ static int handle_show_switches(int fd, int argc, char *argv[])
 static int handle_show_applications(int fd, int argc, char *argv[])
 {
        struct ast_app *a;
+       int like=0, describing=0;
 
        /* try to lock applications list ... */
        if (ast_mutex_lock(&applock)) {
@@ -2560,26 +2563,54 @@ static int handle_show_applications(int fd, int argc, char *argv[])
                return -1;
        }
 
-       /* ... go to first application ... */
-       a = apps; 
-
        /* ... have we got at least one application (first)? no? */
-       if (!a) {
-               ast_cli(fd, "There is no registered applications\n");
+       if (!apps) {
+               ast_cli(fd, "There are no registered applications\n");
                ast_mutex_unlock(&applock);
                return -1;
        }
 
-       /* ... we have applications ... */
-       ast_cli(fd, "\n    -= Registered Asterisk Applications =-\n");
+       /* show applications like <keyword> */
+       if ((argc == 4) && (!strcmp(argv[2], "like"))) {
+               like = 1;
+       } else if ((argc > 3) && (!strcmp(argv[2], "describing"))) {
+               describing = 1;
+       }
+
+       /* show applications describing <keyword1> [<keyword2>] [...] */
+       if ((!like) && (!describing)) {
+               ast_cli(fd, "    -= Registered Asterisk Applications =-\n");
+       } else {
+               ast_cli(fd, "    -= Matching Asterisk Applications =-\n");
+       }
 
        /* ... go through all applications ... */
-       while (a) {
+       for (a = apps; a; a = a->next) {
                /* ... show informations about applications ... */
-               ast_cli(fd,"  %20s: %s\n",
-                       a->name,
-                       a->synopsis ? a->synopsis : "<Synopsis not available>");
-               a = a->next; 
+               int printapp=0;
+
+               if (like) {
+                       if (ast_strcasestr(a->name, argv[3])) {
+                               printapp = 1;
+                       }
+               } else if (describing) {
+                       if (a->description) {
+                               /* Match all words on command line */
+                               int i;
+                               printapp = 1;
+                               for (i=3;i<argc;i++) {
+                                       if (! ast_strcasestr(a->description, argv[i])) {
+                                               printapp = 0;
+                                       }
+                               }
+                       }
+               } else {
+                       printapp = 1;
+               }
+
+               if (printapp) {
+                       ast_cli(fd,"  %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
+               }
        }
 
        /* ... unlock and return */
@@ -2588,6 +2619,35 @@ static int handle_show_applications(int fd, int argc, char *argv[])
        return RESULT_SUCCESS;
 }
 
+static char *complete_show_applications(char *line, char *word, int pos, int state)
+{
+       if (pos == 2) {
+               if (ast_strlen_zero(word)) {
+                       switch (state) {
+                       case 0:
+                               return strdup("like");
+                       case 1:
+                               return strdup("describing");
+                       default:
+                               return NULL;
+                       }
+               } else if (! strncasecmp(word, "like", strlen(word))) {
+                       if (state == 0) {
+                               return strdup("like");
+                       } else {
+                               return NULL;
+                       }
+               } else if (! strncasecmp(word, "describing", strlen(word))) {
+                       if (state == 0) {
+                               return strdup("describing");
+                       } else {
+                               return NULL;
+                       }
+               }
+       }
+       return NULL;
+}
+
 /*
  * 'show dialplan' CLI command implementation functions ...
  */
@@ -2824,7 +2884,7 @@ static int handle_show_dialplan(int fd, int argc, char *argv[])
 static struct ast_cli_entry show_applications_cli = 
        { { "show", "applications", NULL }, 
        handle_show_applications, "Shows registered applications",
-       show_applications_help };
+       show_applications_help, complete_show_applications };
 
 static struct ast_cli_entry show_application_cli =
        { { "show", "application", NULL }, 
diff --git a/utils.c b/utils.c
index c1a03be..756cdfd 100755 (executable)
--- a/utils.c
+++ b/utils.c
@@ -9,6 +9,9 @@
  * the GNU General Public License
  */
 
+#ifdef Linux   /* For strcasestr */
+#define __USE_GNU
+#endif
 #include <ctype.h>
 #include <string.h>
 #include <unistd.h>
@@ -20,6 +23,7 @@
 #include <asterisk/lock.h>
 #include <asterisk/utils.h>
 #include <asterisk/logger.h>
+#include <alloca.h>
 
 static char base64[64];
 static char b2a[256];
@@ -363,3 +367,46 @@ int ast_pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_ro
        return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
 }
 #endif /* ! LINUX */
+
+static char *upper(const char *orig, char *buf, int bufsize)
+{
+       int i;
+       memset(buf, 0, bufsize);
+       for (i=0; i<bufsize - 1; i++) {
+               buf[i] = toupper(orig[i]);
+               if (orig[i] == '\0') {
+                       break;
+               }
+       }
+       return buf;
+}
+
+/* Case-insensitive substring matching */
+#ifndef LINUX
+char *ast_strcasestr(const char *haystack, const char *needle)
+{
+       char *u1, *u2;
+       int u1len = strlen(haystack), u2len = strlen(needle);
+
+       u1 = alloca(u1len);
+       u2 = alloca(u2len);
+       if (u1 && u2) {
+               char *offset;
+               if (u2len > u1len) {
+                       /* Needle bigger than haystack */
+                       return NULL;
+               }
+               offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
+               if (offset) {
+                       /* Return the offset into the original string */
+                       return ((char *)((unsigned int)haystack + (unsigned int)(offset - u1)));
+               } else {
+                       return NULL;
+               }
+       } else {
+               ast_log(LOG_ERROR, "Out of memory\n");
+               return NULL;
+       }
+}
+#endif
+