Newer
Older
ast_mutex_unlock(&applock);
/* 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");
}
for (a = apps; a; a = a->next) {
/* ... show informations about applications ... */
if (strcasestr(a->name, argv[3])) {
}
} else if (describing) {
if (a->description) {
/* Match all words on command line */
int i;
printapp = 1;
if (!strcasestr(a->description, argv[i])) {
}
}
}
} else {
printapp = 1;
}
if (printapp) {
ast_cli(fd," %20s: %s\n", a->name, a->synopsis ? a->synopsis : "<Synopsis not available>");
}
if ((!like) && (!describing)) {
ast_cli(fd, " -= %d Applications Registered =-\n",total_apps);
} else {
ast_cli(fd, " -= %d Applications Matching =-\n",total_match);
}
ast_mutex_unlock(&applock);
Russell Bryant
committed
static char *complete_show_applications(const char *line, const char *word, int pos, int state)
int wordlen = strlen(word);
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", wordlen)) {
if (state == 0) {
return strdup("like");
} else {
return NULL;
}
} else if (! strncasecmp(word, "describing", wordlen)) {
if (state == 0) {
return strdup("describing");
} else {
return NULL;
}
}
}
return NULL;
}
/*
* 'show dialplan' CLI command implementation functions ...
*/
Russell Bryant
committed
static char *complete_show_dialplan_context(const char *line, const char *word, int pos,
struct ast_context *c = NULL;
char *ret = NULL;
/* we are do completion of [exten@]context on second position only */
/* try to lock contexts list ... */
if (ast_lock_contexts()) {
ast_log(LOG_ERROR, "Unable to lock context list\n");
return NULL;
}
if (!strncasecmp(word, ast_get_context_name(c), wordlen)) {
/* ... for serve? ... */
if (++which > state) {
/* ... yes, serve this context name ... */
ret = strdup(ast_get_context_name(c));
break;
/* ... unlock and return */
ast_unlock_contexts();
Mark Spencer
committed
struct dialplan_counters {
int total_context;
int total_exten;
int total_prio;
int context_existence;
int extension_existence;
};
static int show_dialplan_helper(int fd, char *context, char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, char *includes[])
/* try to lock contexts */
if (ast_lock_contexts()) {
ast_log(LOG_WARNING, "Failed to lock contexts list\n");
Mark Spencer
committed
return -1;
/* show this context? */
if (!context ||
!strcmp(ast_get_context_name(c), context)) {
Mark Spencer
committed
dpc->context_existence = 1;
/* try to lock context before walking in ... */
if (!ast_lock_context(c)) {
struct ast_exten *e;
struct ast_include *i;
struct ast_ignorepat *ip;
struct ast_sw *sw;
char buf[256], buf2[256];
int context_info_printed = 0;
/* are we looking for exten too? if yes, we print context
* if we our extension only
*/
if (!exten) {
Mark Spencer
committed
dpc->total_context++;
ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
ast_get_context_name(c), ast_get_context_registrar(c));
context_info_printed = 1;
}
/* walk extensions ... */
Mark Spencer
committed
for (e = ast_walk_context_extensions(c, NULL); e; e = ast_walk_context_extensions(c, e)) {
/* looking for extension? is this our extension? */
if (exten &&
Mark Spencer
committed
!ast_extension_match(ast_get_extension_name(e), exten))
{
/* we are looking for extension and it's not our
* extension, so skip to next extension */
continue;
}
Mark Spencer
committed
dpc->extension_existence = 1;
/* may we print context info? */
if (!context_info_printed) {
Mark Spencer
committed
dpc->total_context++;
if (rinclude) {
/* TODO Print more info about rinclude */
ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
ast_get_context_name(c),
ast_get_context_registrar(c));
} else {
ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
ast_get_context_name(c),
ast_get_context_registrar(c));
}
Mark Spencer
committed
dpc->total_prio++;
/* write extension name and first peer */
bzero(buf, sizeof(buf));
snprintf(buf, sizeof(buf), "'%s' =>",
ast_get_extension_name(e));
prio = ast_get_extension_priority(e);
if (prio == PRIORITY_HINT) {
snprintf(buf2, sizeof(buf2),
"hint: %s",
ast_get_extension_app(e));
} else {
snprintf(buf2, sizeof(buf2),
"%d. %s(%s)",
prio,
ast_get_extension_app(e),
(char *)ast_get_extension_app_data(e));
}
ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2,
ast_get_extension_registrar(e));
Mark Spencer
committed
dpc->total_exten++;
Mark Spencer
committed
for (p=ast_walk_extension_priorities(e, e); p; p=ast_walk_extension_priorities(e, p)) {
dpc->total_prio++;
bzero((void *)buf, sizeof(buf));
if (ast_get_extension_label(p))
snprintf(buf, sizeof(buf), " [%s]", ast_get_extension_label(p));
prio = ast_get_extension_priority(p);
if (prio == PRIORITY_HINT) {
snprintf(buf2, sizeof(buf2),
"hint: %s",
ast_get_extension_app(p));
} else {
snprintf(buf2, sizeof(buf2),
"%d. %s(%s)",
prio,
ast_get_extension_app(p),
(char *)ast_get_extension_app_data(p));
}
Mark Spencer
committed
ast_get_extension_registrar(p));
Mark Spencer
committed
/* walk included and write info ... */
for (i = ast_walk_context_includes(c, NULL); i; i = ast_walk_context_includes(c, i)) {
bzero(buf, sizeof(buf));
snprintf(buf, sizeof(buf), "'%s'",
ast_get_include_name(i));
if (exten) {
/* Check all includes for the requested extension */
if (includecount >= AST_PBX_MAX_STACK) {
ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n");
} else {
int dupe=0;
int x;
for (x=0;x<includecount;x++) {
if (!strcasecmp(includes[x], ast_get_include_name(i))) {
dupe++;
break;
}
}
if (!dupe) {
includes[includecount] = (char *)ast_get_include_name(i);
show_dialplan_helper(fd, (char *)ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
} else {
ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
}
}
Mark Spencer
committed
} else {
ast_cli(fd, " Include => %-45s [%s]\n",
buf, ast_get_include_registrar(i));
}
Mark Spencer
committed
}
Mark Spencer
committed
/* walk ignore patterns and write info ... */
for (ip = ast_walk_context_ignorepats(c, NULL); ip; ip = ast_walk_context_ignorepats(c, ip)) {
Mark Spencer
committed
const char *ipname = ast_get_ignorepat_name(ip);
char ignorepat[AST_MAX_EXTENSION];
snprintf(buf, sizeof(buf), "'%s'", ipname);
snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
if ((!exten) || ast_extension_match(ignorepat, exten)) {
Mark Spencer
committed
buf, ast_get_ignorepat_registrar(ip));
Mark Spencer
committed
}
if (!rinclude) {
for (sw = ast_walk_context_switches(c, NULL); sw; sw = ast_walk_context_switches(c, sw)) {
snprintf(buf, sizeof(buf), "'%s/%s'",
ast_get_switch_name(sw),
ast_get_switch_data(sw));
ast_cli(fd, " Alt. Switch => %-45s [%s]\n",
buf, ast_get_switch_registrar(sw));
}
}
ast_unlock_context(c);
/* if we print something in context, make an empty line */
Mark Spencer
committed
if (context_info_printed) ast_cli(fd, "\r\n");
Mark Spencer
committed
if (dpc->total_exten == old_total_exten) {
/* Nothing new under the sun */
return -1;
} else {
return res;
}
}
static int handle_show_dialplan(int fd, int argc, char *argv[])
{
char *exten = NULL, *context = NULL;
/* Variables used for different counters */
struct dialplan_counters counters;
char *incstack[AST_PBX_MAX_STACK];
Mark Spencer
committed
memset(&counters, 0, sizeof(counters));
if (argc != 2 && argc != 3)
return RESULT_SHOWUSAGE;
Mark Spencer
committed
/* we obtain [exten@]context? if yes, split them ... */
if (argc == 3) {
char *splitter = ast_strdupa(argv[2]);
/* is there a '@' character? */
Russell Bryant
committed
if (splitter && strchr(argv[2], '@')) {
Mark Spencer
committed
/* yes, split into exten & context ... */
exten = strsep(&splitter, "@");
context = splitter;
/* check for length and change to NULL if ast_strlen_zero() */
if (ast_strlen_zero(exten))
exten = NULL;
if (ast_strlen_zero(context))
context = NULL;
show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack);
Mark Spencer
committed
} else {
/* no '@' char, only context given */
context = argv[2];
if (ast_strlen_zero(context))
context = NULL;
show_dialplan_helper(fd, context, exten, &counters, NULL, 0, incstack);
Mark Spencer
committed
}
} else {
/* Show complete dial plan */
show_dialplan_helper(fd, NULL, NULL, &counters, NULL, 0, incstack);
Mark Spencer
committed
}
/* check for input failure and throw some error messages */
Mark Spencer
committed
if (context && !counters.context_existence) {
ast_cli(fd, "There is no existence of '%s' context\n", context);
Mark Spencer
committed
if (exten && !counters.extension_existence) {
if (context)
ast_cli(fd, "There is no existence of %s@%s extension\n",
exten, context);
else
ast_cli(fd,
"There is no existence of '%s' extension in all contexts\n",
exten);
return RESULT_FAILURE;
}
Mark Spencer
committed
ast_cli(fd,"-= %d %s (%d %s) in %d %s. =-\n",
counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
counters.total_context, counters.total_context == 1 ? "context" : "contexts");
Mark Spencer
committed
/*
* CLI entries for upper commands ...
*/
static struct ast_cli_entry pbx_cli[] = {
{ { "show", "applications", NULL }, handle_show_applications,
"Shows registered dialplan applications", show_applications_help, complete_show_applications },
{ { "show", "functions", NULL }, handle_show_functions,
"Shows registered dialplan functions", show_functions_help },
{ { "show" , "function", NULL }, handle_show_function,
"Describe a specific dialplan function", show_function_help, complete_show_function },
{ { "show", "application", NULL }, handle_show_application,
"Describe a specific dialplan application", show_application_help, complete_show_application },
{ { "show", "dialplan", NULL }, handle_show_dialplan,
"Show dialplan", show_dialplan_help, complete_show_dialplan_context },
{ { "show", "switches", NULL }, handle_show_switches,
"Show alternative switches", show_switches_help },
{ { "show", "hints", NULL }, handle_show_hints,
"Show dialplan hints", show_hints_help },
int ast_unregister_application(const char *app)
{
if (ast_mutex_lock(&applock)) {
ast_log(LOG_ERROR, "Unable to lock application list\n");
return -1;
}
if (!strcasecmp(app, tmp->name)) {
if (tmpl)
tmpl->next = tmp->next;
else
apps = tmp->next;
if (option_verbose > 1)
ast_verbose( VERBOSE_PREFIX_2 "Unregistered application '%s'\n", tmp->name);
ast_mutex_unlock(&applock);
ast_mutex_unlock(&applock);
struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar)
struct ast_context *tmp, **local_contexts;
int length;
length = sizeof(struct ast_context);
length += strlen(name) + 1;
if (!extcontexts) {
local_contexts = &contexts;
ast_mutex_lock(&conlock);
} else
local_contexts = extcontexts;
for (tmp = *local_contexts; tmp; tmp = tmp->next) {
ast_mutex_unlock(&conlock);
ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
ast_mutex_unlock(&conlock);
ast_mutex_init(&tmp->lock);
strcpy(tmp->name, name);
if (option_debug)
ast_log(LOG_DEBUG, "Registered context '%s'\n", tmp->name);
else if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Registered extension context '%s'\n", tmp->name);
} else
ast_log(LOG_ERROR, "Out of memory\n");
ast_mutex_unlock(&conlock);
void __ast_context_destroy(struct ast_context *con, const char *registrar);
Kevin P. Fleming
committed
struct store_hint {
char *context;
char *exten;
struct ast_state_cb *callbacks;
int laststate;
AST_LIST_ENTRY(store_hint) list;
char data[1];
};
AST_LIST_HEAD(store_hints, store_hint);
void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar)
{
struct ast_context *tmp, *lasttmp = NULL;
Kevin P. Fleming
committed
struct store_hints store;
struct store_hint *this;
struct ast_hint *hint;
struct ast_exten *exten;
int length;
struct ast_state_cb *thiscb, *prevcb;
/* preserve all watchers for hints associated with this registrar */
AST_LIST_HEAD_INIT(&store);
Russell Bryant
committed
AST_LIST_LOCK(&hints);
AST_LIST_TRAVERSE(&hints, hint, list) {
Kevin P. Fleming
committed
if (hint->callbacks && !strcmp(registrar, hint->exten->parent->registrar)) {
length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2 + sizeof(*this);
this = calloc(1, length);
if (!this) {
ast_log(LOG_WARNING, "Could not allocate memory to preserve hint\n");
continue;
}
this->callbacks = hint->callbacks;
hint->callbacks = NULL;
this->laststate = hint->laststate;
this->context = this->data;
strcpy(this->data, hint->exten->parent->name);
this->exten = this->data + strlen(this->context) + 1;
strcpy(this->exten, hint->exten->exten);
AST_LIST_INSERT_HEAD(&store, this, list);
}
}
Russell Bryant
committed
AST_LIST_UNLOCK(&hints);
Kevin P. Fleming
committed
ast_mutex_lock(&conlock);
Mark Spencer
committed
__ast_context_destroy(NULL,registrar);
while (tmp) {
lasttmp = tmp;
tmp = tmp->next;
}
} else {
while (tmp) {
Mark Spencer
committed
__ast_context_destroy(tmp,tmp->registrar);
}
if (lasttmp) {
lasttmp->next = contexts;
contexts = *extcontexts;
*extcontexts = NULL;
} else
ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
ast_mutex_unlock(&conlock);
Kevin P. Fleming
committed
/* restore the watchers for hints that can be found; notify those that
cannot be restored
*/
while ((this = AST_LIST_REMOVE_HEAD(&store, list))) {
exten = ast_hint_extension(NULL, this->context, this->exten);
/* Find the hint in the list of hints */
Russell Bryant
committed
AST_LIST_LOCK(&hints);
AST_LIST_TRAVERSE(&hints, hint, list) {
Kevin P. Fleming
committed
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
if (hint->exten == exten)
break;
}
if (!exten || !hint) {
/* this hint has been removed, notify the watchers */
prevcb = NULL;
thiscb = this->callbacks;
while (thiscb) {
prevcb = thiscb;
thiscb = thiscb->next;
prevcb->callback(this->context, this->exten, AST_EXTENSION_REMOVED, prevcb->data);
free(prevcb);
}
} else {
thiscb = this->callbacks;
while (thiscb->next)
thiscb = thiscb->next;
thiscb->next = hint->callbacks;
hint->callbacks = this->callbacks;
hint->laststate = this->laststate;
}
Russell Bryant
committed
AST_LIST_UNLOCK(&hints);
Kevin P. Fleming
committed
free(this);
}
int ast_context_add_include(const char *context, const char *include, const char *registrar)
if (ast_lock_contexts()) {
errno = EBUSY;
return -1;
}
/* walk contexts ... */
/* ... search for the right one ... */
if (!strcmp(ast_get_context_name(c), context)) {
int ret = ast_context_add_include2(c, include, registrar);
/* ... unlock contexts list and return */
ast_unlock_contexts();
return ret;
}
}
/* we can't find the right context */
ast_unlock_contexts();
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
/*! \brief Helper for get_range.
* return the index of the matching entry, starting from 1.
* If names is not supplied, try numeric values.
*/
static int lookup_name(const char *s, char *const names[], int max)
{
int i;
if (names) {
for (i = 0; names[i]; i++) {
if (!strcasecmp(s, names[i]))
return i+1;
}
} else if (sscanf(s, "%d", &i) == 1 && i >= 1 && i <= max) {
return i;
}
return 0; /* error return */
}
/*! \brief helper function to return a range up to max (7, 12, 31 respectively).
* names, if supplied, is an array of names that should be mapped to numbers.
*/
static unsigned get_range(char *src, int max, char *const names[], const char *msg)
{
int s, e; /* start and ending position */
unsigned int mask = 0;
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
/* Check for whole range */
if (ast_strlen_zero(src) || !strcmp(src, "*")) {
s = 0;
e = max - 1;
} else {
/* Get start and ending position */
char *c = strchr(src, '-');
if (c)
*c++ = '\0';
/* Find the start */
s = lookup_name(src, names, max);
if (!s) {
ast_log(LOG_WARNING, "Invalid %s '%s', assuming none\n", msg, src);
return 0;
}
s--;
if (c) { /* find end of range */
e = lookup_name(c, names, max);
if (!e) {
ast_log(LOG_WARNING, "Invalid end %s '%s', assuming none\n", msg, c);
return 0;
}
e--;
} else
e = s;
}
/* Fill the mask. Remember that ranges are cyclic */
BJ Weschke
committed
mask = 1 << e; /* initialize with last element */
for ( ; s != e; s++) {
if (s == max)
s = 0 ;
mask |= (1 << s);
}
return mask;
}
/*! \brief store a bitmask of valid times, one bit each 2 minute */
static void get_timerange(struct ast_timing *i, char *times)
{
char *e;
int x;
int s1, s2;
int e1, e2;
/* start disabling all times, fill the fields with 0's, as they may contain garbage */
memset(i->minmask, 0, sizeof(i->minmask));
/* 2-minutes per bit, since the mask has only 32 bits :( */
if (ast_strlen_zero(times) || !strcmp(times, "*")) {
for (x=0; x<24; x++)
i->minmask[x] = 0x3fffffff; /* 30 bits */
return;
}
/* Otherwise expect a range */
e = strchr(times, '-');
if (!e) {
ast_log(LOG_WARNING, "Time range is not valid. Assuming no restrictions based on time.\n");
*e++ = '\0';
/* XXX why skip non digits ? */
e++;
ast_log(LOG_WARNING, "Invalid time range. Assuming no restrictions based on time.\n");
return;
}
if (sscanf(times, "%d:%d", &s1, &s2) != 2) {
ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", times);
return;
}
if (sscanf(e, "%d:%d", &e1, &e2) != 2) {
ast_log(LOG_WARNING, "%s isn't a time. Assuming no restrictions based on time.\n", e);
/* XXX this needs to be optimized */
s1 = s1 * 30 + s2/2;
if ((s1 < 0) || (s1 >= 24*30)) {
ast_log(LOG_WARNING, "%s isn't a valid start time. Assuming no time.\n", times);
if ((e1 < 0) || (e1 >= 24*30)) {
ast_log(LOG_WARNING, "%s isn't a valid end time. Assuming no time.\n", e);
return;
}
/* Go through the time and enable each appropriate bit */
for (x=s1;x != e1;x = (x + 1) % (24 * 30)) {
i->minmask[x/30] |= (1 << (x % 30));
}
/* Do the last one */
i->minmask[x/30] |= (1 << (x % 30));
#else
/* Initialize masks to blank */
i->minmask[cth] = 0;
if (
/* First hour with more than one hour */
(((cth == s1) && (ctm >= s2)) &&
((cth < e1)))
/* Only one hour */
|| (((cth == s1) && (ctm >= s2)) &&
((cth == e1) && (ctm <= e2)))
/* In between first and last hours (more than 2 hours) */
|| ((cth > s1) &&
(cth < e1))
/* Last hour with more than one hour */
|| ((cth > s1) &&
((cth == e1) && (ctm <= e2)))
)
i->minmask[cth] |= (1 << (ctm / 2));
}
}
#endif
}
static char *days[] =
{
"sun",
"mon",
"tue",
"wed",
"thu",
"fri",
"sat",
};
static char *months[] =
{
"jan",
"feb",
"mar",
"apr",
"may",
"jun",
"jul",
"aug",
"sep",
"oct",
"nov",
"dec",
int ast_build_timing(struct ast_timing *i, char *info_in)
char info_save[256];
char *info;
if (ast_strlen_zero(info_in))
return 0;
/* make a copy just in case we were passed a static string */
ast_copy_string(info_save, info_in, sizeof(info_save));
i->monthmask = 0xfff; /* 12 bits */
i->daymask = 0x7fffffffU; /* 31 bits */
i->dowmask = 0x7f; /* 7 bits */
/* on each call, use strsep() to move info to the next argument */
get_timerange(i, strsep(&info, "|"));
if (info)
i->dowmask = get_range(strsep(&info, "|"), 7, days, "day of week");
if (info)
i->daymask = get_range(strsep(&info, "|"), 31, NULL, "day");
if (info)
i->monthmask = get_range(strsep(&info, "|"), 12, months, "month");
return 1;
}
int ast_check_timing(struct ast_timing *i)
{
struct tm tm;
localtime_r(&t,&tm);
/* If it's not the right month, return */
if (!(i->monthmask & (1 << tm.tm_mon)))
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
return 0;
/* If it's not that time of the month.... */
/* Warning, tm_mday has range 1..31! */
if (!(i->daymask & (1 << (tm.tm_mday-1))))
return 0;
/* If it's not the right day of the week */
if (!(i->dowmask & (1 << tm.tm_wday)))
return 0;
/* Sanity check the hour just to be safe */
if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
ast_log(LOG_WARNING, "Insane time...\n");
return 0;
}
/* Now the tough part, we calculate if it fits
in the right time based on min/hour */
if (!(i->minmask[tm.tm_hour] & (1 << (tm.tm_min / 2))))
return 0;
/* If we got this far, then we're good */
return 1;
/*
* errno values
* ENOMEM - out of memory
* EBUSY - can't lock
* EEXIST - already included
* EINVAL - there is no existence of context for inclusion
*/
int ast_context_add_include2(struct ast_context *con, const char *value,
const char *registrar)
struct ast_include *i, *il = NULL; /* include, include_last */
int length;
char *p;
length = sizeof(struct ast_include);
length += 2 * (strlen(value) + 1);
ast_log(LOG_ERROR, "Out of memory\n");
Russell Bryant
committed
/* Fill in this structure. Use 'p' for assignments, as the fields
* in the structure are 'const char *'
*/
p = new_include->stuff;
new_include->name = p;
Russell Bryant
committed
strcpy(p, value);
p += strlen(value) + 1;
new_include->rname = p;
Russell Bryant
committed
strcpy(p, value);
/* Strip off timing info, and process if it is there */
if ( (c = strchr(p, '|')) ) {
*c++ = '\0';
new_include->hastime = ast_build_timing(&(new_include->timing), c);
new_include->next = NULL;
new_include->registrar = registrar;
/* ... try to lock this context ... */
if (ast_mutex_lock(&con->lock)) {
free(new_include);
errno = EBUSY;
return -1;
}
/* ... go to last include and check if context is already included too... */
if (!strcasecmp(i->name, new_include->name)) {
free(new_include);
ast_mutex_unlock(&con->lock);
errno = EEXIST;
return -1;
}
il = i;
}
/* ... include new context into context list, unlock, return */
if (il)
il->next = new_include;
else
con->includes = new_include;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
ast_mutex_unlock(&con->lock);
return 0;
}
/*
* errno values
* EBUSY - can't lock
int ast_context_add_switch(const char *context, const char *sw, const char *data, int eval, const char *registrar)
if (ast_lock_contexts()) {
errno = EBUSY;
return -1;
}
/* walk contexts ... */
/* ... search for the right one ... */
if (!strcmp(ast_get_context_name(c), context)) {
int ret = ast_context_add_switch2(c, sw, data, eval, registrar);
/* ... unlock contexts list and return */
ast_unlock_contexts();
return ret;
}
}
/* we can't find the right context */
ast_unlock_contexts();
return -1;
}
/*
* errno values
* ENOMEM - out of memory
* EBUSY - can't lock
* EEXIST - already included
* EINVAL - there is no existence of context for inclusion
*/
int ast_context_add_switch2(struct ast_context *con, const char *value,
const char *data, int eval, const char *registrar)
struct ast_sw *new_sw;
struct ast_sw *i, *il = NULL; /* sw, sw_last */
int length;
char *p;
length = sizeof(struct ast_sw);
length += strlen(value) + 1;
if (data)
length += strlen(data);
length++;
if (eval) {
/* Create buffer for evaluation of variables */
length += SWITCH_DATA_LENGTH;
length++;
}
ast_log(LOG_ERROR, "Out of memory\n");
p = new_sw->stuff;
new_sw->name = p;
strcpy(new_sw->name, value);
p += strlen(value) + 1;
new_sw->data = p;
if (data) {
strcpy(new_sw->data, data);