Asterisk - The Open Source Telephony Project GIT-master-4f52ed6
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.

Functions

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 []
 

Detailed Description

PBX variables routines.

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

Definition in file pbx_variables.c.

Function Documentation

◆ 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:1815
#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:758
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:1110
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:2837
#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:1136
#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:1059
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:1052
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:783
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 962 of file pbx_variables.c.

963{
964 struct ast_channel *c = NULL;
965 char *fn, *substituted;
966 int ret;
967 char workspace[1024];
968
969 switch (cmd) {
970 case CLI_INIT:
971 e->command = "dialplan eval function";
972 e->usage =
973 "Usage: dialplan eval function <name(args)>\n"
974 " Evaluate a dialplan function call\n"
975 " A dummy channel is used to evaluate\n"
976 " the function call, so only global\n"
977 " variables should be used.\n";
978 return NULL;
979 case CLI_GENERATE:
980 return NULL;
981 }
982
983 if (a->argc != e->args + 1) {
984 return CLI_SHOWUSAGE;
985 }
986
988 if (!c) {
989 ast_cli(a->fd, "Unable to allocate bogus channel for function evaluation.\n");
990 return CLI_FAILURE;
991 }
992
993 fn = (char *) a->argv[3];
994 pbx_substitute_variables_helper(c, fn, workspace, sizeof(workspace));
995 substituted = ast_strdupa(workspace);
996 workspace[0] = '\0';
997 ret = ast_func_read(c, substituted, workspace, sizeof(workspace));
998
1000
1001 ast_cli(a->fd, "Return Value: %s (%d)\n", ret ? "Failure" : "Success", ret);
1002 ast_cli(a->fd, "Result: %s\n", workspace);
1003
1004 return CLI_SUCCESS;
1005}
#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 1029 of file pbx_variables.c.

1030{
1031 struct ast_channel *chan;
1032 const char *chan_name, *var_name, *var_value;
1033
1034 switch (cmd) {
1035 case CLI_INIT:
1036 e->command = "dialplan set chanvar";
1037 e->usage =
1038 "Usage: dialplan set chanvar <channel> <varname> <value>\n"
1039 " Set channel variable <varname> to <value>\n";
1040 return NULL;
1041 case CLI_GENERATE:
1042 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
1043 }
1044
1045 if (a->argc != e->args + 3)
1046 return CLI_SHOWUSAGE;
1047
1048 chan_name = a->argv[e->args];
1049 var_name = a->argv[e->args + 1];
1050 var_value = a->argv[e->args + 2];
1051
1052 if (!(chan = ast_channel_get_by_name(chan_name))) {
1053 ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
1054 return CLI_FAILURE;
1055 }
1056
1057 pbx_builtin_setvar_helper(chan, var_name, var_value);
1058
1059 chan = ast_channel_unref(chan);
1060
1061 ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name);
1062
1063 return CLI_SUCCESS;
1064}
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1448
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 1007 of file pbx_variables.c.

1008{
1009 switch (cmd) {
1010 case CLI_INIT:
1011 e->command = "dialplan set global";
1012 e->usage =
1013 "Usage: dialplan set global <name> <value>\n"
1014 " Set global dialplan variable <name> to <value>\n";
1015 return NULL;
1016 case CLI_GENERATE:
1017 return NULL;
1018 }
1019
1020 if (a->argc != e->args + 2)
1021 return CLI_SHOWUSAGE;
1022
1023 pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
1024 ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
1025
1026 return CLI_SUCCESS;
1027}

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 925 of file pbx_variables.c.

926{
927 struct ast_channel *chan;
928 struct ast_var_t *var;
929
930 switch (cmd) {
931 case CLI_INIT:
932 e->command = "dialplan show chanvar";
933 e->usage =
934 "Usage: dialplan show chanvar <channel>\n"
935 " List current channel variables and their values\n";
936 return NULL;
937 case CLI_GENERATE:
938 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
939 }
940
941 if (a->argc != e->args + 1) {
942 return CLI_SHOWUSAGE;
943 }
944
945 chan = ast_channel_get_by_name(a->argv[e->args]);
946 if (!chan) {
947 ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
948 return CLI_FAILURE;
949 }
950
951 ast_channel_lock(chan);
953 ast_cli(a->fd, "%s=%s\n", ast_var_name(var), ast_var_value(var));
954 }
955 ast_channel_unlock(chan);
956
957 ast_channel_unref(chan);
958 return CLI_SUCCESS;
959}

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 897 of file pbx_variables.c.

898{
899 int i = 0;
900 struct ast_var_t *newvariable;
901
902 switch (cmd) {
903 case CLI_INIT:
904 e->command = "dialplan show globals";
905 e->usage =
906 "Usage: dialplan show globals\n"
907 " List current global dialplan variables and their values\n";
908 return NULL;
909 case CLI_GENERATE:
910 return NULL;
911 }
912
914 AST_LIST_TRAVERSE (&globals, newvariable, entries) {
915 i++;
916 ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
917 }
919 ast_cli(a->fd, "\n -- %d variable(s)\n", i);
920
921 return CLI_SUCCESS;
922}

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 1383 of file pbx_variables.c.

1384{
1385 int res = 0;
1386
1391 AST_TEST_REGISTER(test_variable_substrings);
1392
1393 return res;
1394}
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 1288 of file pbx_variables.c.

1289{
1290 struct ast_var_t *vardata;
1291
1293 while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
1294 ast_var_delete(vardata);
1296}
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 1097 of file pbx_variables.c.

1098{
1099 struct ast_var_t *variables;
1100 const char *ret = NULL;
1101 int i;
1102 struct varshead *places[2] = { NULL, &globals };
1103
1104 if (!name)
1105 return NULL;
1106
1107 if (chan) {
1108 ast_channel_lock(chan);
1109 places[0] = ast_channel_varshead(chan);
1110 }
1111
1112 for (i = 0; i < 2; i++) {
1113 if (!places[i])
1114 continue;
1115 if (places[i] == &globals)
1117 AST_LIST_TRAVERSE(places[i], variables, entries) {
1118 if (!strcmp(name, ast_var_name(variables))) {
1119 ret = ast_var_value(variables);
1120 break;
1121 }
1122 }
1123 if (places[i] == &globals)
1125 if (ret)
1126 break;
1127 }
1128
1129 if (chan)
1130 ast_channel_unlock(chan);
1131
1132 return ret;
1133}
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(), 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 1135 of file pbx_variables.c.

1136{
1137 struct ast_var_t *newvariable;
1138 struct varshead *headp;
1139
1140 if (name[strlen(name)-1] == ')') {
1141 char *function = ast_strdupa(name);
1142
1143 ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
1144 ast_func_write(chan, function, value);
1145 return;
1146 }
1147
1148 if (chan) {
1149 ast_channel_lock(chan);
1150 headp = ast_channel_varshead(chan);
1151 } else {
1153 headp = &globals;
1154 }
1155
1156 if (value && (newvariable = ast_var_assign(name, value))) {
1157 if (headp == &globals)
1158 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
1159 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1160 }
1161
1162 if (chan)
1163 ast_channel_unlock(chan);
1164 else
1166}
#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 1066 of file pbx_variables.c.

1067{
1068 struct ast_var_t *variables;
1069 const char *var, *val;
1070 int total = 0;
1071
1072 if (!chan)
1073 return 0;
1074
1076
1077 ast_channel_lock(chan);
1078
1080 if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
1081 /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
1082 ) {
1083 if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
1084 ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
1085 break;
1086 } else
1087 total++;
1088 } else
1089 break;
1090 }
1091
1092 ast_channel_unlock(chan);
1093
1094 return total;
1095}
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 1226 of file pbx_variables.c.

1227{
1228 char *name, *value, *mydata;
1229
1230 if (ast_strlen_zero(data)) {
1231 ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
1232 return 0;
1233 }
1234
1235 mydata = ast_strdupa(data);
1236 name = strsep(&mydata, "=");
1237 value = mydata;
1238 if (!value) {
1239 ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
1240 return 0;
1241 }
1242
1243 if (strchr(name, ' ')) {
1244 ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
1245 }
1246
1248
1249 return 0;
1250}
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 1168 of file pbx_variables.c.

1169{
1170 struct ast_var_t *newvariable;
1171 struct varshead *headp;
1172 const char *nametail = name;
1173 /*! True if the old value was not an empty string. */
1174 int old_value_existed = 0;
1175
1176 if (name[strlen(name) - 1] == ')') {
1177 char *function = ast_strdupa(name);
1178
1179 return ast_func_write(chan, function, value);
1180 }
1181
1182 if (chan) {
1183 ast_channel_lock(chan);
1184 headp = ast_channel_varshead(chan);
1185 } else {
1187 headp = &globals;
1188 }
1189
1190 /* For comparison purposes, we have to strip leading underscores */
1191 if (*nametail == '_') {
1192 nametail++;
1193 if (*nametail == '_')
1194 nametail++;
1195 }
1196
1197 AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1198 if (strcmp(ast_var_name(newvariable), nametail) == 0) {
1199 /* there is already such a variable, delete it */
1200 AST_LIST_REMOVE_CURRENT(entries);
1201 old_value_existed = !ast_strlen_zero(ast_var_value(newvariable));
1202 ast_var_delete(newvariable);
1203 break;
1204 }
1205 }
1207
1208 if (value && (newvariable = ast_var_assign(name, value))) {
1209 if (headp == &globals) {
1210 ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
1211 }
1212 AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1214 } else if (old_value_existed) {
1215 /* We just deleted a non-empty dialplan variable. */
1217 }
1218
1219 if (chan)
1220 ast_channel_unlock(chan);
1221 else
1223 return 0;
1224}
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 1252 of file pbx_variables.c.

1253{
1254 char *data;
1255 int x;
1257 AST_APP_ARG(pair)[99]; /* parse up to 99 variables */
1258 );
1262 );
1263
1264 if (ast_strlen_zero(vdata)) {
1265 ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
1266 return 0;
1267 }
1268
1269 data = ast_strdupa(vdata);
1271
1272 for (x = 0; x < args.argc; x++) {
1273 AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
1274 if (pair.argc == 2) {
1276 if (strchr(pair.name, ' '))
1277 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);
1278 } else if (!chan) {
1279 ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
1280 } else {
1281 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));
1282 }
1283 }
1284
1285 return 0;
1286}
#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 886 of file pbx_variables.c.

887{
889}
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 665 of file pbx_variables.c.

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

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(), c, voicemailpwcheck::context, ast_channel::exten, len(), LOG_ERROR, LOG_WARNING, NULL, parse_variable_name(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full_location(), substring(), var, and VAR_BUF_SIZE.

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 891 of file pbx_variables.c.

892{
893 pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, NULL);
894}

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 1374 of file pbx_variables.c.

1375{
1380 AST_TEST_UNREGISTER(test_variable_substrings);
1381}
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 1366 of file pbx_variables.c.

Referenced by load_pbx_variables(), and unload_pbx_variables().