- convert the list of dialplan function to the list macros

- add missing locking of the functions list in the "show functions" CLI command


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@23950 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Russell Bryant
2006-05-01 15:09:51 +00:00
parent 48b812829d
commit 992e0c1eed
2 changed files with 44 additions and 82 deletions

View File

@@ -71,7 +71,7 @@ struct ast_custom_function {
const char *syntax; /*!< Syntax description */ const char *syntax; /*!< Syntax description */
int (*read)(struct ast_channel *, char *, char *, char *, size_t); /*!< Read function, if read is supported */ int (*read)(struct ast_channel *, char *, char *, char *, size_t); /*!< Read function, if read is supported */
int (*write)(struct ast_channel *, char *, char *, const char *); /*!< Write function, if write is supported */ int (*write)(struct ast_channel *, char *, char *, const char *); /*!< Write function, if write is supported */
struct ast_custom_function *next; AST_LIST_ENTRY(ast_custom_function) acflist;
}; };
/*! \brief All switch functions have the same interface, so define a type for them */ /*! \brief All switch functions have the same interface, so define a type for them */

122
pbx.c
View File

@@ -244,8 +244,7 @@ static int autofallthrough = 0;
AST_MUTEX_DEFINE_STATIC(maxcalllock); AST_MUTEX_DEFINE_STATIC(maxcalllock);
static int countcalls = 0; static int countcalls = 0;
AST_MUTEX_DEFINE_STATIC(acflock); /*!< Lock for the custom function list */ AST_LIST_HEAD_STATIC(acf_root, ast_custom_function);
static struct ast_custom_function *acf_root = NULL;
/*! \brief Declaration of builtin applications */ /*! \brief Declaration of builtin applications */
static struct pbx_builtin { static struct pbx_builtin {
@@ -1033,16 +1032,18 @@ static int handle_show_functions(int fd, int argc, char *argv[])
ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed"); ast_cli(fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
for (acf = acf_root ; acf; acf = acf->next) { AST_LIST_LOCK(&acf_root);
AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
if (!like || strstr(acf->name, argv[3])) { if (!like || strstr(acf->name, argv[3])) {
count_acf++; count_acf++;
ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis); ast_cli(fd, "%-20.20s %-35.35s %s\n", acf->name, acf->syntax, acf->synopsis);
} }
} }
AST_LIST_UNLOCK(&acf_root);
ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : ""); ast_cli(fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
return 0; return RESULT_SUCCESS;
} }
static int handle_show_function(int fd, int argc, char *argv[]) static int handle_show_function(int fd, int argc, char *argv[])
@@ -1108,121 +1109,82 @@ static char *complete_show_function(const char *line, const char *word, int pos,
int which = 0; int which = 0;
int wordlen = strlen(word); int wordlen = strlen(word);
/* try to lock functions list ... */
if (ast_mutex_lock(&acflock)) {
ast_log(LOG_ERROR, "Unable to lock function list\n");
return NULL;
}
/* case-insensitive for convenience in this 'complete' function */ /* case-insensitive for convenience in this 'complete' function */
for (acf = acf_root; acf && !ret; acf = acf->next) { AST_LIST_LOCK(&acf_root);
if (!strncasecmp(word, acf->name, wordlen) && ++which > state) AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
if (!strncasecmp(word, acf->name, wordlen) && ++which > state) {
ret = strdup(acf->name); ret = strdup(acf->name);
break;
}
} }
AST_LIST_UNLOCK(&acf_root);
ast_mutex_unlock(&acflock);
return ret; return ret;
} }
struct ast_custom_function* ast_custom_function_find(const char *name) struct ast_custom_function *ast_custom_function_find(const char *name)
{ {
struct ast_custom_function *acfptr; struct ast_custom_function *acf = NULL;
/* try to lock functions list ... */ AST_LIST_LOCK(&acf_root);
if (ast_mutex_lock(&acflock)) { AST_LIST_TRAVERSE(&acf_root, acf, acflist) {
ast_log(LOG_ERROR, "Unable to lock function list\n"); if (!strcmp(name, acf->name))
return NULL;
}
for (acfptr = acf_root; acfptr; acfptr = acfptr->next) {
if (!strcmp(name, acfptr->name))
break; break;
} }
AST_LIST_UNLOCK(&acf_root);
ast_mutex_unlock(&acflock); return acf;
return acfptr;
} }
int ast_custom_function_unregister(struct ast_custom_function *acf) int ast_custom_function_unregister(struct ast_custom_function *acf)
{ {
struct ast_custom_function *cur, *prev = NULL; struct ast_custom_function *cur;
int res = -1;
if (!acf) if (!acf)
return -1; return -1;
/* try to lock functions list ... */ AST_LIST_LOCK(&acf_root);
if (ast_mutex_lock(&acflock)) { AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
ast_log(LOG_ERROR, "Unable to lock function list\n");
return -1;
}
for (cur = acf_root; cur; prev = cur, cur = cur->next) {
if (cur == acf) { if (cur == acf) {
if (prev) AST_LIST_REMOVE_CURRENT(&acf_root, acflist);
prev->next = acf->next; if (option_verbose > 1)
else ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
acf_root = acf->next;
res = 0;
break; break;
} }
} }
AST_LIST_TRAVERSE_SAFE_END
AST_LIST_UNLOCK(&acf_root);
ast_mutex_unlock(&acflock); return acf ? 0 : -1;
if (!res && option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Unregistered custom function %s\n", acf->name);
return res;
} }
int ast_custom_function_register(struct ast_custom_function *acf) int ast_custom_function_register(struct ast_custom_function *acf)
{ {
struct ast_custom_function *cur, *last = NULL; struct ast_custom_function *cur;
int found = 0;
if (!acf) if (!acf)
return -1; return -1;
/* try to lock functions list ... */ AST_LIST_LOCK(&acf_root);
if (ast_mutex_lock(&acflock)) {
ast_log(LOG_ERROR, "Unable to lock function list. Failed registering function %s\n", acf->name);
return -1;
}
if (ast_custom_function_find(acf->name)) { if (ast_custom_function_find(acf->name)) {
ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name); ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
ast_mutex_unlock(&acflock); AST_LIST_UNLOCK(&acf_root);
return -1; return -1;
} }
for (cur = acf_root; cur; cur = cur->next) { /* Store in alphabetical order */
if (strcmp(acf->name, cur->name) < 0) { AST_LIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
found = 1; if (strcasecmp(acf->name, cur->name) < 0) {
if (last) { AST_LIST_INSERT_BEFORE_CURRENT(&acf_root, acf, acflist);
acf->next = cur;
last->next = acf;
} else {
acf->next = acf_root;
acf_root = acf;
}
break; break;
} }
last = cur;
} }
AST_LIST_TRAVERSE_SAFE_END
if (!cur)
AST_LIST_INSERT_TAIL(&acf_root, acf, acflist);
/* Wasn't before anything else, put it at the end */ AST_LIST_UNLOCK(&acf_root);
if (!found) {
if (last)
last->next = acf;
else
acf_root = acf;
acf->next = NULL;
}
ast_mutex_unlock(&acflock);
if (option_verbose > 1) if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name); ast_verbose(VERBOSE_PREFIX_2 "Registered custom function %s\n", acf->name);
@@ -2650,7 +2612,7 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
/*! \brief Dynamically register a new dial plan application */ /*! \brief Dynamically register a new dial plan application */
int ast_register_application(const char *app, int (*execute)(struct ast_channel *, void *), const char *synopsis, const char *description) int ast_register_application(const char *app, int (*execute)(struct ast_channel *, void *), const char *synopsis, const char *description)
{ {
struct ast_app *tmp, *prev = NULL; struct ast_app *tmp, *cur = NULL;
char tmps[80]; char tmps[80];
int length; int length;
@@ -2676,14 +2638,14 @@ int ast_register_application(const char *app, int (*execute)(struct ast_channel
tmp->description = description; tmp->description = description;
/* Store in alphabetical order */ /* Store in alphabetical order */
AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, prev, list) { AST_LIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
if (strcasecmp(tmp->name, prev->name) < 0) { if (strcasecmp(tmp->name, cur->name) < 0) {
AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list); AST_LIST_INSERT_BEFORE_CURRENT(&apps, tmp, list);
break; break;
} }
} }
AST_LIST_TRAVERSE_SAFE_END AST_LIST_TRAVERSE_SAFE_END
if (!prev) if (!cur)
AST_LIST_INSERT_TAIL(&apps, tmp, list); AST_LIST_INSERT_TAIL(&apps, tmp, list);
if (option_verbose > 1) if (option_verbose > 1)