Newer
Older
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)
static char* choices[] = { "like", "describing", NULL };
return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
/*
* '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;
}
/* walk through all contexts and return the n-th match */
if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
ret = ast_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");
return (dpc->total_exten == old_total_exten) ? -1 : res;
Mark Spencer
committed
}
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
/*! \brief CLI support for listing global variables in a parseable way */
static int handle_show_globals(int fd, int argc, char *argv[])
{
int i = 0;
struct ast_var_t *newvariable;
ast_mutex_lock(&globalslock);
AST_LIST_TRAVERSE (&globals, newvariable, entries) {
i++;
ast_cli(fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
}
ast_mutex_unlock(&globalslock);
ast_cli(fd, "\n -- %d variables\n", i);
return RESULT_SUCCESS;
}
/*! \brief CLI support for setting global variables */
static int handle_set_global(int fd, int argc, char *argv[])
{
if (argc != 4)
return RESULT_SHOWUSAGE;
pbx_builtin_setvar_helper(NULL, argv[2], argv[3]);
ast_cli(fd, "\n -- Global variable %s set to %s\n", argv[2], argv[3]);
return RESULT_SUCCESS;
}
/*
* 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 },
{ { "show", "globals", NULL }, handle_show_globals,
"Show global dialplan variables", show_globals_help },
{ { "set", "global", NULL }, handle_set_global,
"Set global dialplan variable", set_global_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);
Russell Bryant
committed
if ((tmp = ast_calloc(1, length))) {
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);
Russell Bryant
committed
}
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;
AST_LIST_HEAD_INIT(&store);
/* it is very important that this function hold the hint list lock _and_ the conlock
during its operation; not only do we need to ensure that the list of contexts
and extensions does not change, but also that no hint callbacks (watchers) are
added or removed during the merge/delete process
in addition, the locks _must_ be taken in this order, because there are already
other code paths that use this order
*/
ast_mutex_lock(&conlock);
Russell Bryant
committed
AST_LIST_LOCK(&hints);
/* preserve all watchers for hints associated with this registrar */
Russell Bryant
committed
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);
Russell Bryant
committed
if (!(this = ast_calloc(1, length)))
Kevin P. Fleming
committed
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);
}
}
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");
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_TRAVERSE(&hints, hint, list) {
Kevin P. Fleming
committed
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
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;
}
free(this);
}
AST_LIST_UNLOCK(&hints);
ast_mutex_unlock(&conlock);
int ast_context_add_include(const char *context, const char *include, const char *registrar)
int ret = -1;
struct ast_context *c = find_context_locked(context);
if (c) {
ret = ast_context_add_include2(c, include, registrar);
ast_unlock_contexts();
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
/*! \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;
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
/* 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 */
while (s != e) {
if (s >= max) {
s = 0;
mask |= (1 << s);
} else {
mask |= (1 << s);
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, const 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");
int ast_check_timing(const struct ast_timing *i)
localtime_r(&t,&tm);
/* If it's not the right month, return */
if (!(i->monthmask & (1 << tm.tm_mon)))
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
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);
Russell Bryant
committed
if (!(new_include = ast_calloc(1, length)))
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)
int ret = -1;
struct ast_context *c = find_context_locked(context);
if (c) { /* found, add switch to this context */
ret = ast_context_add_switch2(c, sw, data, eval, registrar);
ast_unlock_contexts();
}
/*
* 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++;
}
Russell Bryant
committed
if (!(new_sw = ast_calloc(1, length)))
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);
p += strlen(data) + 1;
} else {
strcpy(new_sw->data, "");
p++;
}
if (eval)
new_sw->tmpdata = p;
new_sw->eval = eval;
new_sw->registrar = registrar;
/* ... try to lock this context ... */
if (ast_mutex_lock(&con->lock)) {
free(new_sw);
errno = EBUSY;
return -1;
}
/* ... go to last sw and check if context is already swd too... */
if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
ast_mutex_unlock(&con->lock);
errno = EEXIST;
return -1;
}
il = i;
}
/* ... sw new context into context list, unlock, return */
if (il)
il->next = new_sw;
else
con->alts = new_sw;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
ast_mutex_unlock(&con->lock);
return 0;
}
/*
* EBUSY - can't lock
int ast_context_remove_ignorepat(const char *context, const char *ignorepat, const char *registrar)