Newer
Older
ast_log(LOG_ERROR, "Unable to lock application list\n");
return -1;
}
/* ... have we got at least one application (first)? no? */
if (!apps) {
ast_cli(fd, "There are no registered applications\n");
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
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
/*! \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_LIST_TRAVERSE (&globals, newvariable, entries) {
i++;
ast_cli(fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
}
/* ... we have applications ... */
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 variables %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);
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
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
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();
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
/*! \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;
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
/* 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)))
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
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();