Asterisk - The Open Source Telephony Project GIT-master-2de1a68
Macros | Functions | Variables
pbx_variables.c File Reference

PBX variables routines. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/app.h"
#include "asterisk/ast_expr.h"
#include "asterisk/chanvars.h"
#include "asterisk/cli.h"
#include "asterisk/linkedlists.h"
#include "asterisk/lock.h"
#include "asterisk/module.h"
#include "asterisk/paths.h"
#include "asterisk/pbx.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/test.h"
#include "pbx_private.h"
Include dependency graph for pbx_variables.c:

Go to the source code of this file.

Macros

#define MAX_VARIABLE_SUB_RECURSE_DEPTH   15
 

Functions

static void __init_varsub_recurse_level (void)
 Thread local keeping track of recursion depth. More...
 
const char * ast_str_retrieve_variable (struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
 
void ast_str_substitute_variables (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
 
void ast_str_substitute_variables_full (struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, struct varshead *headp, const char *templ, size_t *used)
 
void ast_str_substitute_variables_full2 (struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used, int use_both)
 Perform variable/function/expression substitution on an ast_str. More...
 
void ast_str_substitute_variables_varshead (struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
 
static const char * ast_str_substring (struct ast_str *value, int offset, int length)
 
static char * handle_eval_function (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI support for executing function. More...
 
static char * handle_set_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_set_global (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_show_chanvar (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI support for listing chanvar's variables in a parseable way. More...
 
static char * handle_show_globals (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI support for listing global variables in a parseable way. More...
 
int load_pbx_variables (void)
 
static int parse_variable_name (char *var, int *offset, int *length, int *isfunc)
 extract offset:length from variable name. More...
 
void pbx_builtin_clear_globals (void)
 
const char * pbx_builtin_getvar_helper (struct ast_channel *chan, const char *name)
 Return a pointer to the value of the corresponding channel variable. More...
 
void pbx_builtin_pushvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, without removing any previously set value. More...
 
int pbx_builtin_serialize_variables (struct ast_channel *chan, struct ast_str **buf)
 Create a human-readable string, specifying all variables and their corresponding values. More...
 
int pbx_builtin_setvar (struct ast_channel *chan, const char *data)
 Parse and set a single channel variable, where the name and value are separated with an '=' character. More...
 
int pbx_builtin_setvar_helper (struct ast_channel *chan, const char *name, const char *value)
 Add a variable to the channel variable stack, removing the most recently set value for the same name. More...
 
int pbx_builtin_setvar_multiple (struct ast_channel *chan, const char *vdata)
 Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character. More...
 
void pbx_retrieve_variable (struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
 Support for Asterisk built-in variables in the dialplan. More...
 
void pbx_substitute_variables_helper (struct ast_channel *c, const char *cp1, char *cp2, int count)
 
void pbx_substitute_variables_helper_full (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
 
void pbx_substitute_variables_helper_full_location (struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used, const char *context, const char *exten, int pri)
 Substitutes variables, similar to pbx_substitute_variables_helper_full, but allows passing the context, extension, and priority in. More...
 
void pbx_substitute_variables_varshead (struct varshead *headp, const char *cp1, char *cp2, int count)
 
static char * substring (const char *value, int offset, int length, char *workspace, size_t workspace_len)
 takes a substring. It is ok to call with value == workspace. More...
 
static void unload_pbx_variables (void)
 

Variables

static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
 
static ast_rwlock_t globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} }
 
static struct ast_cli_entry vars_cli []
 
static struct ast_threadstorage varsub_recurse_level = { .once = PTHREAD_ONCE_INIT , .key_init = __init_varsub_recurse_level , .custom_init = NULL , }
 

Detailed Description

PBX variables routines.

Author
Corey Farrell git@c.nosp@m.fwar.nosp@m.e.com

Definition in file pbx_variables.c.

Macro Definition Documentation

◆ MAX_VARIABLE_SUB_RECURSE_DEPTH

#define MAX_VARIABLE_SUB_RECURSE_DEPTH   15

Definition at line 668 of file pbx_variables.c.

Function Documentation

◆ __init_varsub_recurse_level()

static void __init_varsub_recurse_level ( void  )
static

Thread local keeping track of recursion depth.

Definition at line 666 of file pbx_variables.c.

671{

◆ ast_str_retrieve_variable()

const char * ast_str_retrieve_variable ( struct ast_str **  buf,
ssize_t  maxlen,
struct ast_channel chan,
struct varshead headp,
const char *  var 
)
Parameters
bufResult will be placed in this buffer.
maxlen-1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
chanChannel variables from which to extract values, and channel to pass to any dialplan functions.
headpIf no channel is specified, a channel list from which to extract variable values
varVariable name to retrieve.

Definition at line 250 of file pbx_variables.c.

251{
252 const char not_found = '\0';
253 char *tmpvar;
254 const char *ret;
255 const char *s; /* the result */
256 int offset, length;
257 int i, need_substring;
258 struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */
259 char workspace[20];
260
261 if (c) {
263 places[0] = ast_channel_varshead(c);
264 }
265 /*
266 * Make a copy of var because parse_variable_name() modifies the string.
267 * Then if called directly, we might need to run substring() on the result;
268 * remember this for later in 'need_substring', 'offset' and 'length'
269 */
270 tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
271 need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
272
273 /*
274 * Look first into predefined variables, then into variable lists.
275 * Variable 's' points to the result, according to the following rules:
276 * s == &not_found (set at the beginning) means that we did not find a
277 * matching variable and need to look into more places.
278 * If s != &not_found, s is a valid result string as follows:
279 * s = NULL if the variable does not have a value;
280 * you typically do this when looking for an unset predefined variable.
281 * s = workspace if the result has been assembled there;
282 * typically done when the result is built e.g. with an snprintf(),
283 * so we don't need to do an additional copy.
284 * s != workspace in case we have a string, that needs to be copied
285 * (the ast_copy_string is done once for all at the end).
286 * Typically done when the result is already available in some string.
287 */
288 s = &not_found; /* default value */
289 if (c) { /* This group requires a valid channel */
290 /* Names with common parts are looked up a piece at a time using strncmp. */
291 if (!strncmp(var, "CALL", 4)) {
292 if (!strncmp(var + 4, "ING", 3)) {
293 if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */
294 ast_str_set(str, maxlen, "%d",
296 s = ast_str_buffer(*str);
297 } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */
298 ast_str_set(str, maxlen, "%d", ast_channel_caller(c)->ani2);
299 s = ast_str_buffer(*str);
300 } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */
301 ast_str_set(str, maxlen, "%d", ast_channel_caller(c)->id.number.plan);
302 s = ast_str_buffer(*str);
303 } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */
304 ast_str_set(str, maxlen, "%d", ast_channel_dialed(c)->transit_network_select);
305 s = ast_str_buffer(*str);
306 }
307 }
308 } else if (!strcmp(var, "HINT")) {
310 } else if (!strcmp(var, "HINTNAME")) {
312 } else if (!strcmp(var, "EXTEN")) {
313 s = ast_channel_exten(c);
314 } else if (!strcmp(var, "CONTEXT")) {
316 } else if (!strcmp(var, "PRIORITY")) {
317 ast_str_set(str, maxlen, "%d", ast_channel_priority(c));
318 s = ast_str_buffer(*str);
319 } else if (!strcmp(var, "CHANNEL")) {
320 s = ast_channel_name(c);
321 } else if (!strcmp(var, "UNIQUEID")) {
323 } else if (!strcmp(var, "HANGUPCAUSE")) {
324 ast_str_set(str, maxlen, "%d", ast_channel_hangupcause(c));
325 s = ast_str_buffer(*str);
326 }
327 }
328 if (s == &not_found) { /* look for more */
329 if (!strcmp(var, "EPOCH")) {
330 ast_str_set(str, maxlen, "%d", (int) time(NULL));
331 s = ast_str_buffer(*str);
332 } else if (!strcmp(var, "SYSTEMNAME")) {
334 } else if (!strcmp(var, "ASTCACHEDIR")) {
336 } else if (!strcmp(var, "ASTETCDIR")) {
338 } else if (!strcmp(var, "ASTMODDIR")) {
340 } else if (!strcmp(var, "ASTVARLIBDIR")) {
342 } else if (!strcmp(var, "ASTDBDIR")) {
344 } else if (!strcmp(var, "ASTKEYDIR")) {
346 } else if (!strcmp(var, "ASTDATADIR")) {
348 } else if (!strcmp(var, "ASTAGIDIR")) {
350 } else if (!strcmp(var, "ASTSPOOLDIR")) {
352 } else if (!strcmp(var, "ASTRUNDIR")) {
354 } else if (!strcmp(var, "ASTLOGDIR")) {
356 } else if (!strcmp(var, "ASTSBINDIR")) {
358 } else if (!strcmp(var, "ENTITYID")) {
359 ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
360 s = workspace;
361 }
362 }
363 /* if not found, look into chanvars or global vars */
364 for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
365 struct ast_var_t *variables;
366 if (!places[i])
367 continue;
368 if (places[i] == &globals)
370 AST_LIST_TRAVERSE(places[i], variables, entries) {
371 if (!strcmp(ast_var_name(variables), var)) {
372 s = ast_var_value(variables);
373 break;
374 }
375 }
376 if (places[i] == &globals)
378 }
379 if (s == &not_found || s == NULL) {
380 ast_debug(5, "Result of '%s' is NULL\n", var);
381 ret = NULL;
382 } else {
383 ast_debug(5, "Result of '%s' is '%s'\n", var, s);
384 if (s != ast_str_buffer(*str)) {
385 ast_str_set(str, maxlen, "%s", s);
386 }
387 ret = ast_str_buffer(*str);
388 if (need_substring) {
389 ret = ast_str_substring(*str, offset, length);
390 ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
391 }
392 }
393
394 if (c) {
396 }
397 return ret;
398}
const char * str
Definition: app_jack.c:147
#define var
Definition: ast_expr2f.c:605
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
const char * ast_channel_name(const struct ast_channel *chan)
struct varshead * ast_channel_varshead(struct ast_channel *chan)
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:1821
#define ast_channel_lock(chan)
Definition: channel.h:2922
int ast_channel_priority(const struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
int ast_channel_hangupcause(const struct ast_channel *chan)
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
const char * ast_channel_exten(const struct ast_channel *chan)
#define ast_channel_unlock(chan)
Definition: channel.h:2923
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define ast_rwlock_rdlock(a)
Definition: lock.h:235
#define ast_rwlock_unlock(a)
Definition: lock.h:234
const char * ast_config_AST_KEY_DIR
Definition: options.c:161
const char * ast_config_AST_CACHE_DIR
Definition: options.c:150
const char * ast_config_AST_MODULE_DIR
Definition: options.c:153
const char * ast_config_AST_RUN_DIR
Definition: options.c:162
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
const char * ast_config_AST_CONFIG_DIR
Definition: options.c:151
const char * ast_config_AST_SPOOL_DIR
Definition: options.c:154
const char * ast_config_AST_AGI_DIR
Definition: options.c:160
const char * ast_config_AST_VAR_DIR
Definition: options.c:157
const char * ast_config_AST_SYSTEM_NAME
Definition: options.c:170
const char * ast_config_AST_SBIN_DIR
Definition: options.c:163
const char * ast_config_AST_LOG_DIR
Definition: options.c:159
const char * ast_config_AST_DB
Definition: options.c:165
int ast_str_get_hint(struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
If an extension hint exists, return non-zero.
Definition: pbx.c:4155
static ast_rwlock_t globalslock
static const char * ast_str_substring(struct ast_str *value, int offset, int length)
static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
extract offset:length from variable name.
static struct varshead globals
#define NULL
Definition: resample.c:96
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
struct ast_var_t::@211 entries
Number structure.
Definition: app_followme.c:154
static struct test_val c
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: utils.c:2839
#define ARRAY_LEN(a)
Definition: utils.h:666
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:93

References ARRAY_LEN, ast_channel_caller(), ast_channel_context(), ast_channel_dialed(), ast_channel_exten(), ast_channel_hangupcause(), ast_channel_lock, ast_channel_name(), ast_channel_priority(), ast_channel_uniqueid(), ast_channel_unlock, ast_channel_varshead(), ast_config_AST_AGI_DIR, ast_config_AST_CACHE_DIR, ast_config_AST_CONFIG_DIR, ast_config_AST_DATA_DIR, ast_config_AST_DB, ast_config_AST_KEY_DIR, ast_config_AST_LOG_DIR, ast_config_AST_MODULE_DIR, ast_config_AST_RUN_DIR, ast_config_AST_SBIN_DIR, ast_config_AST_SPOOL_DIR, ast_config_AST_SYSTEM_NAME, ast_config_AST_VAR_DIR, ast_debug, ast_eid_default, ast_eid_to_str(), AST_LIST_TRAVERSE, ast_party_id_presentation(), ast_rwlock_rdlock, ast_rwlock_unlock, ast_str_buffer(), ast_str_get_hint(), ast_str_set(), ast_str_substring(), ast_strdupa, ast_var_name(), ast_var_value(), c, ast_var_t::entries, globals, globalslock, NULL, parse_variable_name(), str, and var.

Referenced by ast_ari_asterisk_get_global_var(), ast_ari_channels_get_channel_var(), ast_str_substitute_variables_full2(), and pbx_retrieve_variable().

◆ ast_str_substitute_variables()

void ast_str_substitute_variables ( struct ast_str **  buf,
ssize_t  maxlen,
struct ast_channel chan,
const char *  templ 
)
Parameters
bufResult will be placed in this buffer.
maxlen-1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
chanChannel variables from which to extract values, and channel to pass to any dialplan functions.
templVariable template to expand.

Definition at line 650 of file pbx_variables.c.

651{
652 ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, NULL);
653}
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, struct varshead *headp, const char *templ, size_t *used)

References ast_str_substitute_variables_full(), buf, and NULL.

Referenced by acf_odbc_read(), acf_odbc_write(), ast_pbx_exec_application(), AST_TEST_DEFINE(), cli_odbc_read(), cli_odbc_write(), config_curl(), custom_log(), cut_internal(), destroy_curl(), do_notify(), exec_exec(), func_mchan_read(), function_eval2(), function_fieldnum_helper(), function_fieldqty_helper(), handle_exec(), handle_getvariablefull(), import_helper(), json_decode_read(), listfilter(), make_email_file(), realtime_curl(), realtime_multi_curl(), replace(), require_curl(), sendmail(), sendpage(), shift_pop(), store_curl(), strbetween(), strreplace(), test_2way_function(), test_chan_function(), test_chan_integer(), test_chan_integer_accessor(), test_chan_string(), test_chan_variable(), test_expected_result(), tryexec_exec(), unshift_push(), update2_curl(), and update_curl().

◆ ast_str_substitute_variables_full()

void ast_str_substitute_variables_full ( struct ast_str **  buf,
ssize_t  maxlen,
struct ast_channel c,
struct varshead headp,
const char *  templ,
size_t *  used 
)
Parameters
bufResult will be placed in this buffer.
maxlen-1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
cChannel variables from which to extract values, and channel to pass to any dialplan functions.
headpIf no channel is specified, a channel list from which to extract variable values
templVariable template to expand.
usedNumber of bytes read from the template. (May be NULL)

Definition at line 644 of file pbx_variables.c.

646{
647 ast_str_substitute_variables_full2(buf, maxlen, chan, headp, templ, used, 0);
648}
void ast_str_substitute_variables_full2(struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used, int use_both)
Perform variable/function/expression substitution on an ast_str.

References ast_str_substitute_variables_full2(), and buf.

Referenced by ast_str_substitute_variables(), and ast_str_substitute_variables_varshead().

◆ ast_str_substitute_variables_full2()

void ast_str_substitute_variables_full2 ( struct ast_str **  buf,
ssize_t  maxlen,
struct ast_channel c,
struct varshead headp,
const char *  templ,
size_t *  used,
int  use_both 
)

Perform variable/function/expression substitution on an ast_str.

Parameters
bufResult will be placed in this buffer.
maxlen-1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
cA channel from which to extract values, and to pass to any dialplan functions.
headpA channel variables list to also search for variables.
templVariable template to expand.
usedNumber of bytes read from the template. (May be NULL)
use_bothNormally, if a channel is specified, headp is ignored. If this parameter is set to 1 and both a channel and headp are specified, the channel will be searched for variables first and any not found will be searched for in headp.

Definition at line 400 of file pbx_variables.c.

403{
404 /* Substitutes variables into buf, based on string templ */
405 const char *whereweare;
406 struct ast_str *substr1 = ast_str_create(16);
407 struct ast_str *substr2 = NULL;
408 struct ast_str *substr3 = ast_str_create(16);
409
411
412 if (!substr1 || !substr3) {
413 if (used) {
414 *used = ast_str_strlen(*buf);
415 }
416 ast_free(substr1);
417 ast_free(substr3);
418 return;
419 }
420
421 whereweare = templ;
422 while (!ast_strlen_zero(whereweare)) {
423 const char *nextvar = NULL;
424 const char *nextexp = NULL;
425 const char *nextthing;
426 const char *vars;
427 const char *vare;
428 char *finalvars;
429 int pos;
430 int brackets;
431 int needsub;
432 int len;
433
434 /* reset our buffer */
435 ast_str_reset(substr3);
436
437 /* Determine how much simply needs to be copied to the output buf. */
438 nextthing = strchr(whereweare, '$');
439 if (nextthing) {
440 pos = nextthing - whereweare;
441 switch (nextthing[1]) {
442 case '{':
443 /* Variable substitution */
444 nextvar = nextthing;
445 break;
446 case '[':
447 /* Expression substitution */
448 nextexp = nextthing;
449 break;
450 default:
451 /* '$' is not part of a substitution so include it too. */
452 ++pos;
453 break;
454 }
455 } else {
456 /* We're copying the whole remaining string */
457 pos = strlen(whereweare);
458 }
459
460 if (pos) {
461 /* Copy that many bytes */
462 ast_str_append_substr(buf, maxlen, whereweare, pos);
463
464 whereweare += pos;
465 }
466
467 if (nextvar) {
468 int offset;
469 int offset2;
470 int isfunction;
471 int res;
472
473 /* We have a variable. Find the start and end, and determine
474 if we are going to have to recursively call ourselves on the
475 contents */
476 vars = vare = nextvar + 2;
477 brackets = 1;
478 needsub = 0;
479
480 /* Find the end of it */
481 while (brackets && *vare) {
482 if ((vare[0] == '$') && (vare[1] == '{')) {
483 needsub++;
484 brackets++;
485 vare++;
486 } else if (vare[0] == '{') {
487 brackets++;
488 } else if (vare[0] == '}') {
489 brackets--;
490 } else if ((vare[0] == '$') && (vare[1] == '[')) {
491 needsub++;
492 vare++;
493 }
494 vare++;
495 }
496 len = vare - vars;
497 if (brackets) {
498 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
499 } else {
500 /* Don't count the closing '}' in the length. */
501 --len;
502 }
503
504 /* Skip totally over variable string */
505 whereweare = vare;
506
507 /* Store variable name expression to lookup. */
508 ast_str_set_substr(&substr1, 0, vars, len);
509 ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n",
510 ast_str_buffer(substr1), vars, len);
511
512 /* Substitute if necessary */
513 if (needsub) {
514 if (!substr2) {
515 substr2 = ast_str_create(16);
516 if (!substr2) {
517 continue;
518 }
519 }
520 ast_str_substitute_variables_full2(&substr2, 0, c, headp,
521 ast_str_buffer(substr1), NULL, use_both);
522 finalvars = ast_str_buffer(substr2);
523 } else {
524 finalvars = ast_str_buffer(substr1);
525 }
526
527 parse_variable_name(finalvars, &offset, &offset2, &isfunction);
528 if (isfunction) {
529 /* Evaluate function */
530 res = -1;
531 if (c) {
532 res = ast_func_read2(c, finalvars, &substr3, 0);
533 ast_debug(2, "Function %s result is '%s' from channel\n",
534 finalvars, res ? "" : ast_str_buffer(substr3));
535 }
536 if (!c || (c && res < 0 && use_both)) {
537 struct varshead old;
538 struct ast_channel *bogus;
539
540 bogus = ast_dummy_channel_alloc();
541 if (bogus) {
542 old = *ast_channel_varshead(bogus);
543 if (headp) {
544 *ast_channel_varshead(bogus) = *headp;
545 }
546 res = ast_func_read2(bogus, finalvars, &substr3, 0);
547 /* Don't deallocate the varshead that was passed in */
548 if (headp) {
549 *ast_channel_varshead(bogus) = old;
550 }
551 ast_channel_unref(bogus);
552 } else {
553 ast_log(LOG_ERROR, "Unable to allocate bogus channel for function value substitution.\n");
554 res = -1;
555 }
556 ast_debug(2, "Function %s result is '%s' from headp\n",
557 finalvars, res ? "" : ast_str_buffer(substr3));
558 }
559 } else {
560 const char *result;
561 if (c) {
562 result = ast_str_retrieve_variable(&substr3, 0, c, NULL, finalvars);
563 ast_debug(2, "Variable %s result is '%s' from channel\n",
564 finalvars, S_OR(result, ""));
565 }
566 if (!c || (c && !result && use_both)) {
567 result = ast_str_retrieve_variable(&substr3, 0, NULL, headp, finalvars);
568 ast_debug(2, "Variable %s result is '%s' from headp\n",
569 finalvars, S_OR(result, ""));
570 }
571 res = (result ? 0 : -1);
572 }
573 if (!res) {
574 ast_str_substring(substr3, offset, offset2);
575 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
576 }
577 } else if (nextexp) {
578 /* We have an expression. Find the start and end, and determine
579 if we are going to have to recursively call ourselves on the
580 contents */
581 vars = vare = nextexp + 2;
582 brackets = 1;
583 needsub = 0;
584
585 /* Find the end of it */
586 while (brackets && *vare) {
587 if ((vare[0] == '$') && (vare[1] == '[')) {
588 needsub++;
589 brackets++;
590 vare++;
591 } else if (vare[0] == '[') {
592 brackets++;
593 } else if (vare[0] == ']') {
594 brackets--;
595 } else if ((vare[0] == '$') && (vare[1] == '{')) {
596 needsub++;
597 vare++;
598 }
599 vare++;
600 }
601 len = vare - vars;
602 if (brackets) {
603 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
604 } else {
605 /* Don't count the closing ']' in the length. */
606 --len;
607 }
608
609 /* Skip totally over expression */
610 whereweare = vare;
611
612 /* Store expression to evaluate. */
613 ast_str_set_substr(&substr1, 0, vars, len);
614
615 /* Substitute if necessary */
616 if (needsub) {
617 if (!substr2) {
618 substr2 = ast_str_create(16);
619 if (!substr2) {
620 continue;
621 }
622 }
623 ast_str_substitute_variables_full2(&substr2, 0, c, headp,
624 ast_str_buffer(substr1), NULL, use_both);
625 finalvars = ast_str_buffer(substr2);
626 } else {
627 finalvars = ast_str_buffer(substr1);
628 }
629
630 if (ast_str_expr(&substr3, 0, c, finalvars)) {
631 ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
632 }
633 ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
634 }
635 }
636 if (used) {
637 *used = ast_str_strlen(*buf);
638 }
639 ast_free(substr1);
640 ast_free(substr2);
641 ast_free(substr3);
642}
int ast_str_expr(struct ast_str **str, ssize_t maxlen, struct ast_channel *chan, char *expr)
Evaluate the given expression.
Definition: ast_expr2f.c:2433
#define ast_free(a)
Definition: astmm.h:180
#define ast_log
Definition: astobj2.c:42
static PGresult * result
Definition: cel_pgsql.c:84
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1282
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define LOG_ERROR
#define LOG_WARNING
int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
executes a read operation on a function
const char * ast_str_retrieve_variable(struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
char * ast_str_append_substr(struct ast_str **buf, ssize_t maxlen, const char *src, size_t maxsrc)
Append a non-NULL terminated substring to the end of a dynamic string.
Definition: strings.h:1062
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:693
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
char * ast_str_set_substr(struct ast_str **buf, ssize_t maxlen, const char *src, size_t maxsrc)
Set a dynamic string to a non-NULL terminated substring.
Definition: strings.h:1055
Main Channel structure associated with a channel.
Support for dynamic strings.
Definition: strings.h:623

References ast_channel_unref, ast_channel_varshead(), ast_debug, ast_dummy_channel_alloc, ast_free, ast_func_read2(), ast_log, ast_str_append(), ast_str_append_substr(), ast_str_buffer(), ast_str_create, ast_str_expr(), ast_str_reset(), ast_str_retrieve_variable(), ast_str_set_substr(), ast_str_strlen(), ast_str_substitute_variables_full2(), ast_str_substring(), ast_strlen_zero(), buf, c, len(), LOG_ERROR, LOG_WARNING, NULL, parse_variable_name(), result, and S_OR.

Referenced by ast_str_substitute_variables_full(), ast_str_substitute_variables_full2(), and geoloc_eprofile_resolve_varlist().

◆ ast_str_substitute_variables_varshead()

void ast_str_substitute_variables_varshead ( struct ast_str **  buf,
ssize_t  maxlen,
struct varshead headp,
const char *  templ 
)
Parameters
bufResult will be placed in this buffer.
maxlen-1 if the buffer should not grow, 0 if the buffer may grow to any size, and >0 if the buffer should grow only to that number of bytes.
headpIf no channel is specified, a channel list from which to extract variable values
templVariable template to expand.

Definition at line 655 of file pbx_variables.c.

656{
657 ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, NULL);
658}

References ast_str_substitute_variables_full(), buf, and NULL.

Referenced by add_user_extension(), build_user_routes(), handle_aor(), handle_registrations(), phoneprov_callback(), pp_each_extension_helper(), and pp_each_user_helper().

◆ ast_str_substring()

static const char * ast_str_substring ( struct ast_str value,
int  offset,
int  length 
)
static

Definition at line 187 of file pbx_variables.c.

188{
189 int lr; /* length of the input string after the copy */
190
191 lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
192
193 ast_assert(lr == strlen(ast_str_buffer(value))); /* ast_str_strlen should always agree with strlen */
194
195 /* Quick check if no need to do anything */
196 if (offset == 0 && length >= lr) /* take the whole string */
197 return ast_str_buffer(value);
198
199 if (offset < 0) { /* translate negative offset into positive ones */
200 offset = lr + offset;
201 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
202 offset = 0;
203 }
204
205 /* too large offset result in empty string so we know what to return */
206 if (offset >= lr) {
208 return ast_str_buffer(value);
209 }
210
211 if (offset > 0) {
212 /* Go ahead and chop off the beginning */
213 memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1);
214 lr -= offset;
215 }
216
217 if (length >= 0 && length < lr) { /* truncate if necessary */
218 ast_str_truncate(value, length);
219 } else if (length < 0) {
220 if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
221 ast_str_truncate(value, lr + length);
222 } else {
224 }
225 } else {
226 /* Nothing to do, but update the buffer length */
228 }
229
230 return ast_str_buffer(value);
231}
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Definition: strings.h:786
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
Definition: strings.h:703
int value
Definition: syslog.c:37
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_str_buffer(), ast_str_reset(), ast_str_strlen(), ast_str_truncate(), ast_str_update(), and value.

Referenced by ast_str_retrieve_variable(), and ast_str_substitute_variables_full2().

◆ handle_eval_function()

static char * handle_eval_function ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

CLI support for executing function.

Definition at line 982 of file pbx_variables.c.

983{
984 struct ast_channel *c = NULL;
985 char *fn, *substituted;
986 int ret;
987 char workspace[1024];
988
989 switch (cmd) {
990 case CLI_INIT:
991 e->command = "dialplan eval function";
992 e->usage =
993 "Usage: dialplan eval function <name(args)>\n"
994 " Evaluate a dialplan function call\n"
995 " A dummy channel is used to evaluate\n"
996 " the function call, so only global\n"
997 " variables should be used.\n";
998 return NULL;
999 case CLI_GENERATE:
1000 return NULL;
1001 }
1002
1003 if (a->argc != e->args + 1) {
1004 return CLI_SHOWUSAGE;
1005 }
1006
1008 if (!c) {
1009 ast_cli(a->fd, "Unable to allocate bogus channel for function evaluation.\n");
1010 return CLI_FAILURE;
1011 }
1012
1013 fn = (char *) a->argv[3];
1014 pbx_substitute_variables_helper(c, fn, workspace, sizeof(workspace));
1015 substituted = ast_strdupa(workspace);
1016 workspace[0] = '\0';
1017 ret = ast_func_read(c, substituted, workspace, sizeof(workspace));
1018
1020
1021 ast_cli(a->fd, "Return Value: %s (%d)\n", ret ? "Failure" : "Success", ret);
1022 ast_cli(a->fd, "Result: %s\n", workspace);
1023
1024 return CLI_SUCCESS;
1025}
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
static char * substituted(struct ast_channel *channel, const char *string)
int args
This gets set in ast_cli_register()
Definition: cli.h:185
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static struct test_val a

References a, ast_cli_entry::args, ast_channel_unref, ast_cli(), ast_dummy_channel_alloc, ast_func_read(), ast_strdupa, c, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, pbx_substitute_variables_helper(), substituted(), and ast_cli_entry::usage.

◆ handle_set_chanvar()

static char * handle_set_chanvar ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1049 of file pbx_variables.c.

1050{
1051 struct ast_channel *chan;
1052 const char *chan_name, *var_name, *var_value;
1053
1054 switch (cmd) {
1055 case CLI_INIT:
1056 e->command = "dialplan set chanvar";
1057 e->usage =
1058 "Usage: dialplan set chanvar <channel> <varname> <value>\n"
1059 " Set channel variable <varname> to <value>\n";
1060 return NULL;
1061 case CLI_GENERATE:
1062 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
1063 }
1064
1065 if (a->argc != e->args + 3)
1066 return CLI_SHOWUSAGE;
1067
1068 chan_name = a->argv[e->args];
1069 var_name = a->argv[e->args + 1];
1070 var_value = a->argv[e->args + 2];
1071
1072 if (!(chan = ast_channel_get_by_name(chan_name))) {
1073 ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
1074 return CLI_FAILURE;
1075 }
1076
1077 pbx_builtin_setvar_helper(chan, var_name, var_value);
1078
1079 chan = ast_channel_unref(chan);
1080
1081 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name);
1082
1083 return CLI_SUCCESS;
1084}
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
char * ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
Command completion for the list of active channels.
Definition: main/cli.c:1862
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.

References a, ast_cli_entry::args, ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_complete_channels(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, pbx_builtin_setvar_helper(), and ast_cli_entry::usage.

◆ handle_set_global()

static char * handle_set_global ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1027 of file pbx_variables.c.

1028{
1029 switch (cmd) {
1030 case CLI_INIT:
1031 e->command = "dialplan set global";
1032 e->usage =
1033 "Usage: dialplan set global <name> <value>\n"
1034 " Set global dialplan variable <name> to <value>\n";
1035 return NULL;
1036 case CLI_GENERATE:
1037 return NULL;
1038 }
1039
1040 if (a->argc != e->args + 2)
1041 return CLI_SHOWUSAGE;
1042
1043 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
1044 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
1045
1046 return CLI_SUCCESS;
1047}

References a, ast_cli_entry::args, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, pbx_builtin_setvar_helper(), and ast_cli_entry::usage.

◆ handle_show_chanvar()

static char * handle_show_chanvar ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

CLI support for listing chanvar's variables in a parseable way.

Definition at line 945 of file pbx_variables.c.

946{
947 struct ast_channel *chan;
948 struct ast_var_t *var;
949
950 switch (cmd) {
951 case CLI_INIT:
952 e->command = "dialplan show chanvar";
953 e->usage =
954 "Usage: dialplan show chanvar <channel>\n"
955 " List current channel variables and their values\n";
956 return NULL;
957 case CLI_GENERATE:
958 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
959 }
960
961 if (a->argc != e->args + 1) {
962 return CLI_SHOWUSAGE;
963 }
964
965 chan = ast_channel_get_by_name(a->argv[e->args]);
966 if (!chan) {
967 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
968 return CLI_FAILURE;
969 }
970
971 ast_channel_lock(chan);
973 ast_cli(a->fd, "%s=%s\n", ast_var_name(var), ast_var_value(var));
974 }
975 ast_channel_unlock(chan);
976
977 ast_channel_unref(chan);
978 return CLI_SUCCESS;
979}

References a, ast_cli_entry::args, ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_channel_varshead(), ast_cli(), ast_complete_channels(), AST_LIST_TRAVERSE, ast_var_name(), ast_var_value(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_var_t::entries, NULL, ast_cli_entry::usage, and var.

◆ handle_show_globals()

static char * handle_show_globals ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

CLI support for listing global variables in a parseable way.

Definition at line 917 of file pbx_variables.c.

918{
919 int i = 0;
920 struct ast_var_t *newvariable;
921
922 switch (cmd) {
923 case CLI_INIT:
924 e->command = "dialplan show globals";
925 e->usage =
926 "Usage: dialplan show globals\n"
927 " List current global dialplan variables and their values\n";
928 return NULL;
929 case CLI_GENERATE:
930 return NULL;
931 }
932
934 AST_LIST_TRAVERSE (&globals, newvariable, entries) {
935 i++;
936 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
937 }
939 ast_cli(a->fd, "\n -- %d variable(s)\n", i);
940
941 return CLI_SUCCESS;
942}

References a, ast_cli(), AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_var_t::entries, globals, globalslock, NULL, and ast_cli_entry::usage.

◆ load_pbx_variables()

int load_pbx_variables ( void  )

Provided by pbx_variables.c

Definition at line 1403 of file pbx_variables.c.

1404{
1405 int res = 0;
1406
1411 AST_TEST_REGISTER(test_variable_substrings);
1412
1413 return res;
1414}
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
int ast_register_application2(const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
Register an application.
Definition: pbx_app.c:103
int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
Parse and set a single channel variable, where the name and value are separated with an '=' character...
static struct ast_cli_entry vars_cli[]
static void unload_pbx_variables(void)
int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *vdata)
Parse and set multiple channel variables, where the pairs are separated by the ',' character,...
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

References ARRAY_LEN, ast_cli_register_multiple, ast_register_application2(), ast_register_cleanup(), AST_TEST_REGISTER, NULL, pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), unload_pbx_variables(), and vars_cli.

Referenced by asterisk_daemon().

◆ parse_variable_name()

static int parse_variable_name ( char *  var,
int *  offset,
int *  length,
int *  isfunc 
)
static

extract offset:length from variable name.

Returns
1 if there is a offset:length part, which is trimmed off (values go into variables)

Definition at line 118 of file pbx_variables.c.

119{
120 int parens = 0;
121
122 *offset = 0;
123 *length = INT_MAX;
124 *isfunc = 0;
125 for (; *var; var++) {
126 if (*var == '(') {
127 (*isfunc)++;
128 parens++;
129 } else if (*var == ')') {
130 parens--;
131 } else if (*var == ':' && parens == 0) {
132 *var++ = '\0';
133 sscanf(var, "%30d:%30d", offset, length);
134 return 1; /* offset:length valid */
135 }
136 }
137 return 0;
138}

References var.

Referenced by ast_str_retrieve_variable(), ast_str_substitute_variables_full2(), and pbx_substitute_variables_helper_full_location().

◆ pbx_builtin_clear_globals()

void pbx_builtin_clear_globals ( void  )

Definition at line 1308 of file pbx_variables.c.

1309{
1310 struct ast_var_t *vardata;
1311
1313 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
1314 ast_var_delete(vardata);
1316}
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2471
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define ast_rwlock_wrlock(a)
Definition: lock.h:236

References AST_LIST_REMOVE_HEAD, ast_rwlock_unlock, ast_rwlock_wrlock, ast_var_delete(), ast_var_t::entries, globals, and globalslock.

Referenced by handle_cli_dialplan_reload(), reload(), and unload_pbx_variables().

◆ pbx_builtin_getvar_helper()

const char * pbx_builtin_getvar_helper ( struct ast_channel chan,
const char *  name 
)

Return a pointer to the value of the corresponding channel variable.

Note
Will lock the channel.
This function will return a pointer to the buffer inside the channel variable. This value should only be accessed with the channel locked. If the value needs to be kept around, it should be done by using the following thread-safe code:
const char *var;
if ((var = pbx_builtin_getvar_helper(chan, "MYVAR"))) {
}
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.

Definition at line 1117 of file pbx_variables.c.

1118{
1119 struct ast_var_t *variables;
1120 const char *ret = NULL;
1121 int i;
1122 struct varshead *places[2] = { NULL, &globals };
1123
1124 if (!name)
1125 return NULL;
1126
1127 if (chan) {
1128 ast_channel_lock(chan);
1129 places[0] = ast_channel_varshead(chan);
1130 }
1131
1132 for (i = 0; i < 2; i++) {
1133 if (!places[i])
1134 continue;
1135 if (places[i] == &globals)
1137 AST_LIST_TRAVERSE(places[i], variables, entries) {
1138 if (!strcmp(name, ast_var_name(variables))) {
1139 ret = ast_var_value(variables);
1140 break;
1141 }
1142 }
1143 if (places[i] == &globals)
1145 if (ret)
1146 break;
1147 }
1148
1149 if (chan)
1150 ast_channel_unlock(chan);
1151
1152 return ret;
1153}
static const char name[]
Definition: format_mp3.c:68

References ast_channel_lock, ast_channel_unlock, ast_channel_varshead(), AST_LIST_TRAVERSE, ast_rwlock_rdlock, ast_rwlock_unlock, ast_var_name(), ast_var_value(), globals, globalslock, name, and NULL.

Referenced by __ast_pbx_run(), _while_exec(), action_agents(), add_header_from_channel_var(), agent_handle_show_specific(), agent_login_channel_config(), agent_request_exec(), agent_show_requested(), analog_call(), array(), ast_bridge_call_with_flags(), ast_bridge_timelimit(), ast_bridge_transfer_attended(), ast_call_forward(), ast_channel_connected_line_sub(), ast_channel_redirecting_sub(), ast_eivr_getvariable(), ast_get_chan_applicationmap(), ast_unreal_hangup(), attended_transfer_exec(), bridge_parking_push(), channel_get_external_vars(), check_bridge_play_sound(), common_exec(), conf_run(), create_dynamic_lot_full(), crement_function_read(), dahdi_hangup(), dial_exec_full(), do_forward(), dundi_exec(), eagi_exec(), feature_automixmonitor(), feature_blind_transfer(), find_by_mark(), find_channel_parking_lot_name(), find_conf_realtime(), func_channel_read(), generate_parked_user(), generic_fax_exec(), get_index(), get_transfer_context(), get_transfer_exten(), global_exists_read(), global_read(), gosub_run(), handle_call_forward(), handle_exec(), handle_gosub(), handle_hangup(), hash_read(), iax2_call(), iax2_exec(), if_helper(), leave_voicemail(), local_read(), manager_mixmonitor(), meetme_menu_admin_extended(), minivm_delete_exec(), minivm_notify_exec(), morsecode_exec(), notify_new_message(), ooh323_call(), ooh323_hangup(), park_app_exec(), pbx_builtin_gotoiftime(), permit_dtmf_interrupt(), pre_bridge_setup(), queue_exec(), receive_ademco_event(), refer_blind_callback(), report_receive_fax_status(), report_send_fax_status(), retrydial_exec(), run_agi(), sayunixtime_exec(), sendtext_exec(), set_from_header(), set_touch_variable(), set_transfer_variables_all(), setup_mixmonitor(), setup_park_common_datastore(), sla_trunk_exec(), speech_background(), transfer_refer(), try_calling(), variable_exists_read(), and wait_for_answer().

◆ pbx_builtin_pushvar_helper()

void pbx_builtin_pushvar_helper ( struct ast_channel chan,
const char *  name,
const char *  value 
)

Add a variable to the channel variable stack, without removing any previously set value.

Note
Will lock the channel.

Definition at line 1155 of file pbx_variables.c.

1156{
1157 struct ast_var_t *newvariable;
1158 struct varshead *headp;
1159
1160 if (name[strlen(name)-1] == ')') {
1161 char *function = ast_strdupa(name);
1162
1163 ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
1164 ast_func_write(chan, function, value);
1165 return;
1166 }
1167
1168 if (chan) {
1169 ast_channel_lock(chan);
1170 headp = ast_channel_varshead(chan);
1171 } else {
1173 headp = &globals;
1174 }
1175
1176 if (value && (newvariable = ast_var_assign(name, value))) {
1177 if (headp == &globals)
1178 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
1179 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1180 }
1181
1182 if (chan)
1183 ast_channel_unlock(chan);
1184 else
1186}
#define ast_var_assign(name, value)
Definition: chanvars.h:40
#define ast_verb(level,...)
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
executes a write operation on a function

References ast_channel_lock, ast_channel_unlock, ast_channel_varshead(), ast_func_write(), AST_LIST_INSERT_HEAD, ast_log, ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_var_assign, ast_verb, globals, globalslock, LOG_WARNING, name, and value.

Referenced by acf_odbc_read(), acf_odbc_write(), cli_odbc_read(), cli_odbc_write(), and frame_set_var().

◆ pbx_builtin_serialize_variables()

int pbx_builtin_serialize_variables ( struct ast_channel chan,
struct ast_str **  buf 
)

Create a human-readable string, specifying all variables and their corresponding values.

Parameters
chanChannel from which to read variables
bufDynamic string in which to place the result (should be allocated with ast_str_create).
See also
ast_str_create
Note
Will lock the channel.

Definition at line 1086 of file pbx_variables.c.

1087{
1088 struct ast_var_t *variables;
1089 const char *var, *val;
1090 int total = 0;
1091
1092 if (!chan)
1093 return 0;
1094
1096
1097 ast_channel_lock(chan);
1098
1100 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
1101 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
1102 ) {
1103 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
1104 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
1105 break;
1106 } else
1107 total++;
1108 } else
1109 break;
1110 }
1111
1112 ast_channel_unlock(chan);
1113
1114 return total;
1115}
static int total
Definition: res_adsi.c:970
Definition: ast_expr2.c:325

References ast_channel_lock, ast_channel_unlock, ast_channel_varshead(), AST_LIST_TRAVERSE, ast_log, ast_str_append(), ast_str_reset(), ast_var_name(), ast_var_value(), buf, ast_var_t::entries, LOG_ERROR, total, and var.

Referenced by ast_var_channels_table(), and dumpchan_exec().

◆ pbx_builtin_setvar()

int pbx_builtin_setvar ( struct ast_channel chan,
const char *  data 
)

Parse and set a single channel variable, where the name and value are separated with an '=' character.

Note
Will lock the channel.

Definition at line 1246 of file pbx_variables.c.

1247{
1248 char *name, *value, *mydata;
1249
1250 if (ast_strlen_zero(data)) {
1251 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
1252 return 0;
1253 }
1254
1255 mydata = ast_strdupa(data);
1256 name = strsep(&mydata, "=");
1257 value = mydata;
1258 if (!value) {
1259 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
1260 return 0;
1261 }
1262
1263 if (strchr(name, ' ')) {
1264 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
1265 }
1266
1268
1269 return 0;
1270}
char * strsep(char **str, const char *delims)

References ast_log, ast_strdupa, ast_strlen_zero(), LOG_WARNING, name, pbx_builtin_setvar_helper(), strsep(), and value.

Referenced by ast_compile_ael2(), and load_pbx_variables().

◆ pbx_builtin_setvar_helper()

int pbx_builtin_setvar_helper ( struct ast_channel chan,
const char *  name,
const char *  value 
)

Add a variable to the channel variable stack, removing the most recently set value for the same name.

Note
Will lock the channel. May also be used to set a channel dialplan function to a particular value.
See also
ast_func_write
Returns
-1 if the dialplan function fails to be set
Version
1.8 changed the function to return an error code

True if the old value was not an empty string.

Definition at line 1188 of file pbx_variables.c.

1189{
1190 struct ast_var_t *newvariable;
1191 struct varshead *headp;
1192 const char *nametail = name;
1193 /*! True if the old value was not an empty string. */
1194 int old_value_existed = 0;
1195
1196 if (name[strlen(name) - 1] == ')') {
1197 char *function = ast_strdupa(name);
1198
1199 return ast_func_write(chan, function, value);
1200 }
1201
1202 if (chan) {
1203 ast_channel_lock(chan);
1204 headp = ast_channel_varshead(chan);
1205 } else {
1207 headp = &globals;
1208 }
1209
1210 /* For comparison purposes, we have to strip leading underscores */
1211 if (*nametail == '_') {
1212 nametail++;
1213 if (*nametail == '_')
1214 nametail++;
1215 }
1216
1217 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1218 if (strcmp(ast_var_name(newvariable), nametail) == 0) {
1219 /* there is already such a variable, delete it */
1220 AST_LIST_REMOVE_CURRENT(entries);
1221 old_value_existed = !ast_strlen_zero(ast_var_value(newvariable));
1222 ast_var_delete(newvariable);
1223 break;
1224 }
1225 }
1227
1228 if (value && (newvariable = ast_var_assign(name, value))) {
1229 if (headp == &globals) {
1230 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
1231 }
1232 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1234 } else if (old_value_existed) {
1235 /* We just deleted a non-empty dialplan variable. */
1237 }
1238
1239 if (chan)
1240 ast_channel_unlock(chan);
1241 else
1243 return 0;
1244}
void ast_channel_publish_varset(struct ast_channel *chan, const char *variable, const char *value)
Publish a ast_channel_publish_varset for a channel.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557

References ast_channel_lock, ast_channel_publish_varset(), ast_channel_unlock, ast_channel_varshead(), ast_func_write(), AST_LIST_INSERT_HEAD, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_rwlock_unlock, ast_rwlock_wrlock, ast_strdupa, ast_strlen_zero(), ast_var_assign, ast_var_delete(), ast_var_name(), ast_var_value(), ast_verb, globals, globalslock, name, and value.

Referenced by __analog_ss_thread(), __ast_pbx_run(), _while_exec(), acf_curl_helper(), acf_fetch(), acf_odbc_read(), acf_odbc_write(), acf_transaction_write(), action_atxfer(), action_kick_last(), action_setvar(), admin_exec(), agent_login_exec(), agent_request_exec(), agi_exec_full(), analog_ss_thread(), app_control_set_channel_var(), app_exec(), aqm_exec(), array(), ast_ari_asterisk_set_global_var(), ast_bridge_set_transfer_variables(), ast_bridge_vars_set(), ast_call_forward(), ast_cc_agent_set_interfaces_chanvar(), ast_eivr_setvariable(), ast_iax2_new(), ast_pbx_outgoing_exten_predial(), ast_pickup_call(), ast_rtp_instance_set_stats_vars(), ast_set_cc_interfaces_chanvar(), ast_set_variables(), AST_TEST_DEFINE(), ast_unreal_hangup(), asyncgoto_exec(), attended_transfer_bridge(), attended_transfer_exec(), audiosocket_request(), background_detect_exec(), begin_dial_channel(), blind_transfer_bridge(), blind_transfer_exec(), bridge_channel_internal_push_full(), bridge_exec(), bridgeadd_exec(), calendar_write_exec(), caller_joined_bridge(), caller_safety_timeout(), cccancel_exec(), ccreq_exec(), chan_pjsip_cng_tone_detected(), chan_pjsip_new(), chanavail_exec(), channel_spy(), check_bridge_play_sound(), clear_agent_status(), commit_exec(), conf_run(), confbridge_exec(), confkick_exec(), controlplayback_exec(), count_exec(), crement_function_read(), dahdi_handle_dtmf(), dahdi_new(), delete_write(), dial_exec_full(), dial_transfer(), directory_exec(), disa_exec(), do_directory(), do_forward(), do_notify(), do_waiting(), dtmf_store_framehook(), dynamic_dtmf_hook_callback(), end_bridge_callback(), execute_menu_entry(), fax_detect_framehook(), frame_set_var(), func_export_write(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), geoloc_profile_read(), geoloc_profile_write(), global_delete_write(), global_write(), gosub_release_frame(), gosub_run(), handle_controlstreamfile(), handle_gosub(), handle_incoming_request(), handle_outgoing_response(), handle_response_cmgr(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), handle_streamfile(), hash_read(), hash_write(), if_helper(), isAnsweringMachine(), kick_conference_participant(), launch_monitor_thread(), leave_marked(), leave_queue(), leave_voicemail(), lua_set_variable(), lua_set_variable_value(), manager_park(), mbl_status_exec(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), mixmonitor_exec(), msg_send_exec(), my_handle_dtmf(), onModeChanged(), ooh323_new(), ooh323_rtp_read(), originate_exec(), parking_duration_callback(), parking_timeout_set_caller_features(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_builtin_waitdigit(), pbx_load_config(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), queue_exec(), read_exec(), read_mf_digits(), read_mf_exec(), read_sf_digits(), read_sf_exec(), readexten_exec(), realtimefield_read(), receivefax_exec(), record_abandoned(), record_exec(), recvtext_exec(), refer_blind_callback(), reload_exec(), reload_module(), return_exec(), ring_entry(), rollback_exec(), rotate_file(), rqm_exec(), scan_exec(), select_entry(), select_item_menu(), select_item_seq(), sendfax_exec(), sendtext_exec(), set(), set_channel_variables(), set_duration_var(), set_queue_result(), set_sipdomain_variable(), shift_pop(), signal_exec(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), speech_create(), start_automixmonitor(), system_exec_helper(), test_chan_variable(), testtime_write(), transfer_exec(), tryexec_exec(), unicast_rtp_request(), unshift_push(), update_qe_rule(), upqm_exec(), user_timeout(), vm_exec(), vm_playmsgexec(), vmauthenticate(), wait_exec(), wait_for_answer(), wait_for_signal_or_hangup(), waitforcond_exec(), waitsignal_exec(), waituntil_exec(), and zapateller_exec().

◆ pbx_builtin_setvar_multiple()

int pbx_builtin_setvar_multiple ( struct ast_channel chan,
const char *  data 
)

Parse and set multiple channel variables, where the pairs are separated by the ',' character, and name and value are separated with an '=' character.

Note
Will lock the channel.

Definition at line 1272 of file pbx_variables.c.

1273{
1274 char *data;
1275 int x;
1277 AST_APP_ARG(pair)[99]; /* parse up to 99 variables */
1278 );
1282 );
1283
1284 if (ast_strlen_zero(vdata)) {
1285 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
1286 return 0;
1287 }
1288
1289 data = ast_strdupa(vdata);
1291
1292 for (x = 0; x < args.argc; x++) {
1293 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
1294 if (pair.argc == 2) {
1296 if (strchr(pair.name, ' '))
1297 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", pair.name, pair.value);
1298 } else if (!chan) {
1299 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
1300 } else {
1301 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, ast_channel_exten(chan), ast_channel_context(chan), ast_channel_priority(chan));
1302 }
1303 }
1304
1305 return 0;
1306}
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
const char * name
Definition: test_config.c:85
const char * args

References args, AST_APP_ARG, ast_channel_context(), ast_channel_exten(), ast_channel_priority(), AST_DECLARE_APP_ARGS, ast_log, AST_NONSTANDARD_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), LOG_WARNING, name, pair::name, pbx_builtin_setvar_helper(), and value.

Referenced by load_pbx_variables(), queue_function_var(), set_queue_variables(), and try_calling().

◆ pbx_retrieve_variable()

void pbx_retrieve_variable ( struct ast_channel c,
const char *  var,
char **  ret,
char *  workspace,
int  workspacelen,
struct varshead headp 
)

Support for Asterisk built-in variables in the dialplan.

Retrieve the value of a builtin variable or variable from the channel variable stack.

Note
See also

Definition at line 239 of file pbx_variables.c.

240{
241 struct ast_str *str = ast_str_create(16);
242 const char *cret;
243
244 cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
245 ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
246 *ret = cret ? workspace : NULL;
247 ast_free(str);
248}
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425

References ast_copy_string(), ast_free, ast_str_buffer(), ast_str_create, ast_str_retrieve_variable(), c, NULL, str, and var.

Referenced by action_getvar(), generate_status(), handle_getvariable(), lua_get_variable(), lua_get_variable_value(), and pbx_substitute_variables_helper_full_location().

◆ pbx_substitute_variables_helper()

void pbx_substitute_variables_helper ( struct ast_channel c,
const char *  cp1,
char *  cp2,
int  count 
)

Definition at line 906 of file pbx_variables.c.

907{
909}
void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)

References ast_channel_varshead(), c, NULL, and pbx_substitute_variables_helper_full().

Referenced by handle_eval_function().

◆ pbx_substitute_variables_helper_full()

void pbx_substitute_variables_helper_full ( struct ast_channel c,
struct varshead headp,
const char *  cp1,
char *  cp2,
int  count,
size_t *  used 
)

Definition at line 660 of file pbx_variables.c.

661{
662 pbx_substitute_variables_helper_full_location(c, headp, cp1, cp2, count, used, NULL, NULL, 0);
663}
void pbx_substitute_variables_helper_full_location(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used, const char *context, const char *exten, int pri)
Substitutes variables, similar to pbx_substitute_variables_helper_full, but allows passing the contex...

References c, NULL, and pbx_substitute_variables_helper_full_location().

Referenced by pbx_substitute_variables_helper(), and pbx_substitute_variables_varshead().

◆ pbx_substitute_variables_helper_full_location()

void pbx_substitute_variables_helper_full_location ( struct ast_channel c,
struct varshead headp,
const char *  cp1,
char *  cp2,
int  count,
size_t *  used,
const char *  context,
const char *  exten,
int  pri 
)

Substitutes variables, similar to pbx_substitute_variables_helper_full, but allows passing the context, extension, and priority in.

Definition at line 670 of file pbx_variables.c.

671{
672 /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */
673 const char *whereweare;
674 const char *orig_cp2 = cp2;
675 char ltmp[VAR_BUF_SIZE];
676 char var[VAR_BUF_SIZE];
677 int *recurse_depth;
678
679 *cp2 = 0; /* just in case nothing ends up there */
680
681 /* It is possible to craft dialplan that will recurse indefinitely and cause a stack overflow.
682 * This is symptomatic of a dialplan bug, so abort substitution rather than crash. */
683 recurse_depth = ast_threadstorage_get(&varsub_recurse_level, sizeof(*recurse_depth));
684 if (!recurse_depth) {
685 return;
686 }
687 if ((*recurse_depth)++ >= MAX_VARIABLE_SUB_RECURSE_DEPTH) {
688 ast_log(LOG_ERROR, "Exceeded maximum variable substitution recursion depth (%d) - possible infinite recursion in dialplan?\n", MAX_VARIABLE_SUB_RECURSE_DEPTH);
689 (*recurse_depth)--;
690 return;
691 }
692
693 whereweare = cp1;
694 while (!ast_strlen_zero(whereweare) && count) {
695 char *nextvar = NULL;
696 char *nextexp = NULL;
697 char *nextthing;
698 char *vars;
699 char *vare;
700 int length;
701 int pos;
702 int brackets;
703 int needsub;
704 int len;
705
706 /* Determine how much simply needs to be copied to the output buf. */
707 nextthing = strchr(whereweare, '$');
708 if (nextthing) {
709 pos = nextthing - whereweare;
710 switch (nextthing[1]) {
711 case '{':
712 /* Variable substitution */
713 nextvar = nextthing;
714 break;
715 case '[':
716 /* Expression substitution */
717 nextexp = nextthing;
718 break;
719 default:
720 /* '$' is not part of a substitution so include it too. */
721 ++pos;
722 break;
723 }
724 } else {
725 /* We're copying the whole remaining string */
726 pos = strlen(whereweare);
727 }
728
729 if (pos) {
730 /* Can't copy more than 'count' bytes */
731 if (pos > count)
732 pos = count;
733
734 /* Copy that many bytes */
735 memcpy(cp2, whereweare, pos);
736
737 count -= pos;
738 cp2 += pos;
739 whereweare += pos;
740 *cp2 = 0;
741 }
742
743 if (nextvar) {
744 int offset;
745 int offset2;
746 int isfunction;
747 char *cp4 = NULL;
748 char workspace[VAR_BUF_SIZE] = "";
749
750 /* We have a variable. Find the start and end, and determine
751 if we are going to have to recursively call ourselves on the
752 contents */
753 vars = vare = nextvar + 2;
754 brackets = 1;
755 needsub = 0;
756
757 /* Find the end of it */
758 while (brackets && *vare) {
759 if ((vare[0] == '$') && (vare[1] == '{')) {
760 needsub++;
761 brackets++;
762 vare++;
763 } else if (vare[0] == '{') {
764 brackets++;
765 } else if (vare[0] == '}') {
766 brackets--;
767 } else if ((vare[0] == '$') && (vare[1] == '[')) {
768 needsub++;
769 vare++;
770 }
771 vare++;
772 }
773 len = vare - vars;
774 if (brackets) {
775 ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
776 } else {
777 /* Don't count the closing '}' in the length. */
778 --len;
779 }
780
781 /* Skip totally over variable string */
782 whereweare = vare;
783
784 /* Store variable name expression to lookup (and truncate). */
785 ast_copy_string(var, vars, len + 1);
786
787 /* Substitute if necessary */
788 if (needsub) {
790 vars = ltmp;
791 } else {
792 vars = var;
793 }
794
795 parse_variable_name(vars, &offset, &offset2, &isfunction);
796 if (isfunction) {
797 /* Evaluate function */
798 if (c || !headp)
799 cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
800 else {
801 struct varshead old;
802 struct ast_channel *bogus;
803
804 bogus = ast_dummy_channel_alloc();
805 if (bogus) {
806 old = *ast_channel_varshead(bogus);
807 *ast_channel_varshead(bogus) = *headp;
808 cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
809 /* Don't deallocate the varshead that was passed in */
810 *ast_channel_varshead(bogus) = old;
811 ast_channel_unref(bogus);
812 } else {
813 ast_log(LOG_ERROR, "Unable to allocate bogus channel for function value substitution.\n");
814 cp4 = NULL;
815 }
816 }
817 ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
818 } else {
819 /* Retrieve variable value */
820 /* For dialplan location, if we were told what to substitute explicitly, use that instead */
821 if (exten && !strcmp(vars, "EXTEN")) {
823 cp4 = workspace;
824 } else if (context && !strcmp(vars, "CONTEXT")) {
826 cp4 = workspace;
827 } else if (pri && !strcmp(vars, "PRIORITY")) {
828 snprintf(workspace, VAR_BUF_SIZE, "%d", pri);
829 cp4 = workspace;
830 } else {
831 pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
832 }
833 }
834 if (cp4) {
835 cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
836
837 length = strlen(cp4);
838 if (length > count)
839 length = count;
840 memcpy(cp2, cp4, length);
841 count -= length;
842 cp2 += length;
843 *cp2 = 0;
844 }
845 } else if (nextexp) {
846 /* We have an expression. Find the start and end, and determine
847 if we are going to have to recursively call ourselves on the
848 contents */
849 vars = vare = nextexp + 2;
850 brackets = 1;
851 needsub = 0;
852
853 /* Find the end of it */
854 while (brackets && *vare) {
855 if ((vare[0] == '$') && (vare[1] == '[')) {
856 needsub++;
857 brackets++;
858 vare++;
859 } else if (vare[0] == '[') {
860 brackets++;
861 } else if (vare[0] == ']') {
862 brackets--;
863 } else if ((vare[0] == '$') && (vare[1] == '{')) {
864 needsub++;
865 vare++;
866 }
867 vare++;
868 }
869 len = vare - vars;
870 if (brackets) {
871 ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
872 } else {
873 /* Don't count the closing ']' in the length. */
874 --len;
875 }
876
877 /* Skip totally over expression */
878 whereweare = vare;
879
880 /* Store expression to evaluate (and truncate). */
881 ast_copy_string(var, vars, len + 1);
882
883 /* Substitute if necessary */
884 if (needsub) {
886 vars = ltmp;
887 } else {
888 vars = var;
889 }
890
891 length = ast_expr(vars, cp2, count, c);
892 if (length) {
893 ast_debug(1, "Expression result is '%s'\n", cp2);
894 count -= length;
895 cp2 += length;
896 *cp2 = 0;
897 }
898 }
899 }
900 if (used) {
901 *used = cp2 - orig_cp2;
902 }
903 (*recurse_depth)--;
904}
int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan)
Evaluate the given expression.
Definition: ast_expr2f.c:2391
#define VAR_BUF_SIZE
Definition: pbx_private.h:68
static char * substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
takes a substring. It is ok to call with value == workspace.
void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
Support for Asterisk built-in variables in the dialplan.
static struct ast_threadstorage varsub_recurse_level
#define MAX_VARIABLE_SUB_RECURSE_DEPTH
char exten[AST_MAX_EXTENSION]
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.

References ast_channel_unref, ast_channel_varshead(), ast_copy_string(), ast_debug, ast_dummy_channel_alloc, ast_expr(), ast_func_read(), ast_log, ast_strlen_zero(), ast_threadstorage_get(), c, voicemailpwcheck::context, ast_channel::exten, len(), LOG_ERROR, LOG_WARNING, MAX_VARIABLE_SUB_RECURSE_DEPTH, NULL, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full_location(), substring(), var, VAR_BUF_SIZE, and varsub_recurse_level.

Referenced by eval_exten_read(), pbx_substitute_variables_helper_full(), and pbx_substitute_variables_helper_full_location().

◆ pbx_substitute_variables_varshead()

void pbx_substitute_variables_varshead ( struct varshead headp,
const char *  cp1,
char *  cp2,
int  count 
)

Definition at line 911 of file pbx_variables.c.

912{
913 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, NULL);
914}

References NULL, and pbx_substitute_variables_helper_full().

Referenced by do_say(), dundi_lookup_local(), get_mapping_weight(), and loopback_subst().

◆ substring()

static char * substring ( const char *  value,
int  offset,
int  length,
char *  workspace,
size_t  workspace_len 
)
static

takes a substring. It is ok to call with value == workspace.

Parameters
value
offset< 0 means start from the end of the string and set the beginning to be that many characters back.
lengthis the length of the substring, a value less than 0 means to leave that many off the end.
workspace
workspace_lenAlways return a copy in workspace.

Definition at line 151 of file pbx_variables.c.

152{
153 char *ret = workspace;
154 int lr; /* length of the input string after the copy */
155
156 ast_copy_string(workspace, value, workspace_len); /* always make a copy */
157
158 lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
159
160 /* Quick check if no need to do anything */
161 if (offset == 0 && length >= lr) /* take the whole string */
162 return ret;
163
164 if (offset < 0) { /* translate negative offset into positive ones */
165 offset = lr + offset;
166 if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
167 offset = 0;
168 }
169
170 /* too large offset result in empty string so we know what to return */
171 if (offset >= lr)
172 return ret + lr; /* the final '\0' */
173
174 ret += offset; /* move to the start position */
175 if (length >= 0 && length < lr - offset) /* truncate if necessary */
176 ret[length] = '\0';
177 else if (length < 0) {
178 if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
179 ret[lr + length - offset] = '\0';
180 else
181 ret[0] = '\0';
182 }
183
184 return ret;
185}

References ast_copy_string(), and value.

Referenced by pbx_substitute_variables_helper_full_location().

◆ unload_pbx_variables()

static void unload_pbx_variables ( void  )
static

Definition at line 1394 of file pbx_variables.c.

1395{
1400 AST_TEST_UNREGISTER(test_variable_substrings);
1401}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
void pbx_builtin_clear_globals(void)
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

References ARRAY_LEN, ast_cli_unregister_multiple(), AST_TEST_UNREGISTER, ast_unregister_application(), pbx_builtin_clear_globals(), and vars_cli.

Referenced by load_pbx_variables().

Variable Documentation

◆ globals

struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
static

◆ globalslock

ast_rwlock_t globalslock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} }
static

◆ vars_cli

struct ast_cli_entry vars_cli[]
static

Definition at line 1386 of file pbx_variables.c.

Referenced by load_pbx_variables(), and unload_pbx_variables().

◆ varsub_recurse_level

struct ast_threadstorage varsub_recurse_level = { .once = PTHREAD_ONCE_INIT , .key_init = __init_varsub_recurse_level , .custom_init = NULL , }
static

Definition at line 666 of file pbx_variables.c.

Referenced by pbx_substitute_variables_helper_full_location().