static void shared_variable_free(void *data) { struct varshead *varshead = data; struct ast_var_t *var; while ((var = AST_LIST_REMOVE_HEAD(varshead, entries))) { ast_var_delete(var); } ast_free(varshead); }
void ast_var_list_destroy(struct varshead *head) { struct ast_var_t *var; if (!head) { return; } while ((var = AST_LIST_REMOVE_HEAD(head, entries))) { ast_var_delete(var); } ast_free(head); }
static char *loopback_helper(char *buf, int buflen, const char *exten, const char *context, int priority, const char *data) { struct ast_var_t *newvariable; struct varshead headp; char tmp[80]; snprintf(tmp, sizeof(tmp), "%d", priority); memset(buf, 0, buflen); AST_LIST_HEAD_INIT_NOLOCK(&headp); AST_LIST_INSERT_HEAD(&headp, ast_var_assign("EXTEN", exten), entries); AST_LIST_INSERT_HEAD(&headp, ast_var_assign("CONTEXT", context), entries); AST_LIST_INSERT_HEAD(&headp, ast_var_assign("PRIORITY", tmp), entries); /* Substitute variables */ pbx_substitute_variables_varshead(&headp, data, buf, buflen); /* free the list */ while ((newvariable = AST_LIST_REMOVE_HEAD(&headp, entries))) ast_var_delete(newvariable); return buf; }
/*! \brief * the string is 'prefix:data' or prefix:fmt:data' * with ':' being invalid in strings. */ static int do_say(say_args_t *a, const char *s, const char *options, int depth) { struct ast_variable *v; char *lang, *x, *rule = NULL; int ret = 0; struct varshead head = { .first = NULL, .last = NULL }; struct ast_var_t *n; ast_debug(2, "string <%s> depth <%d>\n", s, depth); if (depth++ > 10) { ast_log(LOG_WARNING, "recursion too deep, exiting\n"); return -1; } else if (!say_cfg) { ast_log(LOG_WARNING, "no say.conf, cannot spell '%s'\n", s); return -1; } /* scan languages same as in file.c */ if (a->language == NULL) a->language = "en"; /* default */ ast_debug(2, "try <%s> in <%s>\n", s, a->language); lang = ast_strdupa(a->language); for (;;) { for (v = ast_variable_browse(say_cfg, lang); v ; v = v->next) { if (ast_extension_match(v->name, s)) { rule = ast_strdupa(v->value); break; } } if (rule) break; if ( (x = strchr(lang, '_')) ) *x = '\0'; /* try without suffix */ else if (strcmp(lang, "en")) lang = "en"; /* last resort, try 'en' if not done yet */ else break; } if (!rule) return 0; /* skip up to two prefixes to get the value */ if ( (x = strchr(s, ':')) ) s = x + 1; if ( (x = strchr(s, ':')) ) s = x + 1; ast_debug(2, "value is <%s>\n", s); n = ast_var_assign("SAY", s); if (!n) { ast_log(LOG_ERROR, "Memory allocation error in do_say\n"); return -1; } AST_LIST_INSERT_HEAD(&head, n, entries); /* scan the body, one piece at a time */ while ( !ret && (x = strsep(&rule, ",")) ) { /* exit on key */ char fn[128]; const char *p, *fmt, *data; /* format and data pointers */ /* prepare a decent file name */ x = ast_skip_blanks(x); ast_trim_blanks(x); /* replace variables */ pbx_substitute_variables_varshead(&head, x, fn, sizeof(fn)); ast_debug(2, "doing [%s]\n", fn); /* locate prefix and data, if any */ fmt = strchr(fn, ':'); if (!fmt || fmt == fn) { /* regular filename */ ret = s_streamwait3(a, fn); continue; } fmt++; data = strchr(fmt, ':'); /* colon before data */ if (!data || data == fmt) { /* simple prefix-fmt */ ret = do_say(a, fn, options, depth); continue; } /* prefix:fmt:data */ for (p = fmt; p < data && ret <= 0; p++) { char fn2[sizeof(fn)]; if (*p == ' ' || *p == '\t') /* skip blanks */ continue; if (*p == '\'') {/* file name - we trim them */ char *y; strcpy(fn2, ast_skip_blanks(p+1)); /* make a full copy */ y = strchr(fn2, '\''); if (!y) { p = data; /* invalid. prepare to end */ break; } *y = '\0'; ast_trim_blanks(fn2); p = strchr(p+1, '\''); ret = s_streamwait3(a, fn2); } else { int l = fmt-fn; strcpy(fn2, fn); /* copy everything */ /* after prefix, append the format */ fn2[l++] = *p; strcpy(fn2 + l, data); ret = do_say(a, fn2, options, depth); } if (ret) { break; } } } ast_var_delete(n); return ret; }