Asterisk - The Open Source Telephony Project  18.5.0
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 "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 *c, struct varshead *headp, const char *templ, size_t *used)
 
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_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_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 246 of file pbx_variables.c.

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_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(), ast_var_t::entries, globalslock, NULL, and parse_variable_name().

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

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

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

References ast_str_substitute_variables_full(), and NULL.

Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), 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_getvariablefull(), import_helper(), listfilter(), make_email_file(), realtime_curl(), realtime_multi_curl(), replace(), require_curl(), run_app_helper(), sendmail(), sendpage(), shift_pop(), store_curl(), strreplace(), syslog_log(), 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().

617 {
618  ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, NULL);
619 }
#define NULL
Definition: resample.c:96
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)

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

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_substring(), ast_strlen_zero, len(), LOG_ERROR, LOG_WARNING, NULL, and parse_variable_name().

Referenced by ast_str_substitute_variables(), and ast_str_substitute_variables_varshead().

395 {
396  /* Substitutes variables into buf, based on string templ */
397  const char *whereweare;
398  struct ast_str *substr1 = ast_str_create(16);
399  struct ast_str *substr2 = NULL;
400  struct ast_str *substr3 = ast_str_create(16);
401 
402  ast_str_reset(*buf);
403 
404  if (!substr1 || !substr3) {
405  if (used) {
406  *used = ast_str_strlen(*buf);
407  }
408  ast_free(substr1);
409  ast_free(substr3);
410  return;
411  }
412 
413  whereweare = templ;
414  while (!ast_strlen_zero(whereweare)) {
415  const char *nextvar = NULL;
416  const char *nextexp = NULL;
417  const char *nextthing;
418  const char *vars;
419  const char *vare;
420  char *finalvars;
421  int pos;
422  int brackets;
423  int needsub;
424  int len;
425 
426  /* reset our buffer */
427  ast_str_reset(substr3);
428 
429  /* Determine how much simply needs to be copied to the output buf. */
430  nextthing = strchr(whereweare, '$');
431  if (nextthing) {
432  pos = nextthing - whereweare;
433  switch (nextthing[1]) {
434  case '{':
435  /* Variable substitution */
436  nextvar = nextthing;
437  break;
438  case '[':
439  /* Expression substitution */
440  nextexp = nextthing;
441  break;
442  default:
443  /* '$' is not part of a substitution so include it too. */
444  ++pos;
445  break;
446  }
447  } else {
448  /* We're copying the whole remaining string */
449  pos = strlen(whereweare);
450  }
451 
452  if (pos) {
453  /* Copy that many bytes */
454  ast_str_append_substr(buf, maxlen, whereweare, pos);
455 
456  whereweare += pos;
457  }
458 
459  if (nextvar) {
460  int offset;
461  int offset2;
462  int isfunction;
463  int res;
464 
465  /* We have a variable. Find the start and end, and determine
466  if we are going to have to recursively call ourselves on the
467  contents */
468  vars = vare = nextvar + 2;
469  brackets = 1;
470  needsub = 0;
471 
472  /* Find the end of it */
473  while (brackets && *vare) {
474  if ((vare[0] == '$') && (vare[1] == '{')) {
475  needsub++;
476  brackets++;
477  vare++;
478  } else if (vare[0] == '{') {
479  brackets++;
480  } else if (vare[0] == '}') {
481  brackets--;
482  } else if ((vare[0] == '$') && (vare[1] == '[')) {
483  needsub++;
484  vare++;
485  }
486  vare++;
487  }
488  len = vare - vars;
489  if (brackets) {
490  ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
491  } else {
492  /* Don't count the closing '}' in the length. */
493  --len;
494  }
495 
496  /* Skip totally over variable string */
497  whereweare = vare;
498 
499  /* Store variable name expression to lookup. */
500  ast_str_set_substr(&substr1, 0, vars, len);
501  ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
502 
503  /* Substitute if necessary */
504  if (needsub) {
505  if (!substr2) {
506  substr2 = ast_str_create(16);
507  if (!substr2) {
508  continue;
509  }
510  }
511  ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), NULL);
512  finalvars = ast_str_buffer(substr2);
513  } else {
514  finalvars = ast_str_buffer(substr1);
515  }
516 
517  parse_variable_name(finalvars, &offset, &offset2, &isfunction);
518  if (isfunction) {
519  /* Evaluate function */
520  if (c || !headp) {
521  res = ast_func_read2(c, finalvars, &substr3, 0);
522  } else {
523  struct varshead old;
524  struct ast_channel *bogus;
525 
526  bogus = ast_dummy_channel_alloc();
527  if (bogus) {
528  old = *ast_channel_varshead(bogus);
529  *ast_channel_varshead(bogus) = *headp;
530  res = ast_func_read2(bogus, finalvars, &substr3, 0);
531  /* Don't deallocate the varshead that was passed in */
532  *ast_channel_varshead(bogus) = old;
533  ast_channel_unref(bogus);
534  } else {
535  ast_log(LOG_ERROR, "Unable to allocate bogus channel for function value substitution.\n");
536  res = -1;
537  }
538  }
539  ast_debug(2, "Function %s result is '%s'\n",
540  finalvars, res ? "" : ast_str_buffer(substr3));
541  } else {
542  /* Retrieve variable value */
543  ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
544  res = 0;
545  }
546  if (!res) {
547  ast_str_substring(substr3, offset, offset2);
548  ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
549  }
550  } else if (nextexp) {
551  /* We have an expression. Find the start and end, and determine
552  if we are going to have to recursively call ourselves on the
553  contents */
554  vars = vare = nextexp + 2;
555  brackets = 1;
556  needsub = 0;
557 
558  /* Find the end of it */
559  while (brackets && *vare) {
560  if ((vare[0] == '$') && (vare[1] == '[')) {
561  needsub++;
562  brackets++;
563  vare++;
564  } else if (vare[0] == '[') {
565  brackets++;
566  } else if (vare[0] == ']') {
567  brackets--;
568  } else if ((vare[0] == '$') && (vare[1] == '{')) {
569  needsub++;
570  vare++;
571  }
572  vare++;
573  }
574  len = vare - vars;
575  if (brackets) {
576  ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
577  } else {
578  /* Don't count the closing ']' in the length. */
579  --len;
580  }
581 
582  /* Skip totally over expression */
583  whereweare = vare;
584 
585  /* Store expression to evaluate. */
586  ast_str_set_substr(&substr1, 0, vars, len);
587 
588  /* Substitute if necessary */
589  if (needsub) {
590  if (!substr2) {
591  substr2 = ast_str_create(16);
592  if (!substr2) {
593  continue;
594  }
595  }
596  ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), NULL);
597  finalvars = ast_str_buffer(substr2);
598  } else {
599  finalvars = ast_str_buffer(substr1);
600  }
601 
602  if (ast_str_expr(&substr3, 0, c, finalvars)) {
603  ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
604  }
605  ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
606  }
607  }
608  if (used) {
609  *used = ast_str_strlen(*buf);
610  }
611  ast_free(substr1);
612  ast_free(substr2);
613  ast_free(substr3);
614 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
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
static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
extract offset:length from variable name.
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
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:1091
struct varshead * ast_channel_varshead(struct ast_channel *chan)
#define NULL
Definition: resample.c:96
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)
#define ast_strlen_zero(foo)
Definition: strings.h:52
static const char * ast_str_substring(struct ast_str *value, int offset, int length)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1283
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:1014
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_free(a)
Definition: astmm.h:182
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:2447
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:653
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
const char * ast_str_retrieve_variable(struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
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:1007
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

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

References ast_str_substitute_variables_full(), and NULL.

Referenced by build_user_routes(), handle_aor(), handle_registrations(), and pp_each_extension_helper().

622 {
623  ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, NULL);
624 }
#define NULL
Definition: resample.c:96
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)

◆ ast_str_substring()

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

Definition at line 185 of file pbx_variables.c.

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

Referenced by ast_str_retrieve_variable(), and ast_str_substitute_variables_full().

186 {
187  int lr; /* length of the input string after the copy */
188 
189  lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
190 
191  /* Quick check if no need to do anything */
192  if (offset == 0 && length >= lr) /* take the whole string */
193  return ast_str_buffer(value);
194 
195  if (offset < 0) { /* translate negative offset into positive ones */
196  offset = lr + offset;
197  if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
198  offset = 0;
199  }
200 
201  /* too large offset result in empty string so we know what to return */
202  if (offset >= lr) {
203  ast_str_reset(value);
204  return ast_str_buffer(value);
205  }
206 
207  if (offset > 0) {
208  /* Go ahead and chop off the beginning */
209  memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1);
210  lr -= offset;
211  }
212 
213  if (length >= 0 && length < lr) { /* truncate if necessary */
214  ast_str_truncate(value, length);
215  } else if (length < 0) {
216  if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
217  ast_str_truncate(value, lr + length);
218  } else {
219  ast_str_reset(value);
220  }
221  } else {
222  /* Nothing to do, but update the buffer length */
223  ast_str_update(value);
224  }
225 
226  return ast_str_buffer(value);
227 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Definition: strings.h:738
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:653
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
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:663

◆ handle_set_chanvar()

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

Definition at line 932 of file pbx_variables.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, 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, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NULL, pbx_builtin_setvar_helper(), ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

933 {
934  struct ast_channel *chan;
935  const char *chan_name, *var_name, *var_value;
936 
937  switch (cmd) {
938  case CLI_INIT:
939  e->command = "dialplan set chanvar";
940  e->usage =
941  "Usage: dialplan set chanvar <channel> <varname> <value>\n"
942  " Set channel variable <varname> to <value>\n";
943  return NULL;
944  case CLI_GENERATE:
945  return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
946  }
947 
948  if (a->argc != e->args + 3)
949  return CLI_SHOWUSAGE;
950 
951  chan_name = a->argv[e->args];
952  var_name = a->argv[e->args + 1];
953  var_value = a->argv[e->args + 2];
954 
955  if (!(chan = ast_channel_get_by_name(chan_name))) {
956  ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
957  return CLI_FAILURE;
958  }
959 
960  pbx_builtin_setvar_helper(chan, var_name, var_value);
961 
962  chan = ast_channel_unref(chan);
963 
964  ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name);
965 
966  return CLI_SUCCESS;
967 }
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const char * line
Definition: cli.h:162
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
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...
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
const int pos
Definition: cli.h:164
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:1830
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454

◆ handle_set_global()

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

Definition at line 910 of file pbx_variables.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NULL, pbx_builtin_setvar_helper(), and ast_cli_entry::usage.

911 {
912  switch (cmd) {
913  case CLI_INIT:
914  e->command = "dialplan set global";
915  e->usage =
916  "Usage: dialplan set global <name> <value>\n"
917  " Set global dialplan variable <name> to <value>\n";
918  return NULL;
919  case CLI_GENERATE:
920  return NULL;
921  }
922 
923  if (a->argc != e->args + 2)
924  return CLI_SHOWUSAGE;
925 
926  pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
927  ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
928 
929  return CLI_SUCCESS;
930 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
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...
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44

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

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, 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, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NULL, ast_cli_args::pos, ast_cli_entry::usage, var, and ast_cli_args::word.

875 {
876  struct ast_channel *chan;
877  struct ast_var_t *var;
878 
879  switch (cmd) {
880  case CLI_INIT:
881  e->command = "dialplan show chanvar";
882  e->usage =
883  "Usage: dialplan show chanvar <channel>\n"
884  " List current channel variables and their values\n";
885  return NULL;
886  case CLI_GENERATE:
887  return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
888  }
889 
890  if (a->argc != e->args + 1) {
891  return CLI_SHOWUSAGE;
892  }
893 
894  chan = ast_channel_get_by_name(a->argv[e->args]);
895  if (!chan) {
896  ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
897  return CLI_FAILURE;
898  }
899 
900  ast_channel_lock(chan);
902  ast_cli(a->fd, "%s=%s\n", ast_var_name(var), ast_var_value(var));
903  }
904  ast_channel_unlock(chan);
905 
906  ast_channel_unref(chan);
907  return CLI_SUCCESS;
908 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
const int argc
Definition: cli.h:160
#define var
Definition: ast_expr2f.c:614
Definition: cli.h:152
struct varshead * ast_channel_varshead(struct ast_channel *chan)
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const char * line
Definition: cli.h:162
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
struct ast_var_t::@249 entries
const char * word
Definition: cli.h:163
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
const int pos
Definition: cli.h:164
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:1830
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454

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

References 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, ast_cli_args::fd, globalslock, NULL, and ast_cli_entry::usage.

847 {
848  int i = 0;
849  struct ast_var_t *newvariable;
850 
851  switch (cmd) {
852  case CLI_INIT:
853  e->command = "dialplan show globals";
854  e->usage =
855  "Usage: dialplan show globals\n"
856  " List current global dialplan variables and their values\n";
857  return NULL;
858  case CLI_GENERATE:
859  return NULL;
860  }
861 
863  AST_LIST_TRAVERSE (&globals, newvariable, entries) {
864  i++;
865  ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
866  }
868  ast_cli(a->fd, "\n -- %d variable(s)\n", i);
869 
870  return CLI_SUCCESS;
871 }
#define ast_rwlock_rdlock(a)
Definition: lock.h:233
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define ast_rwlock_unlock(a)
Definition: lock.h:232
const int fd
Definition: cli.h:159
static struct varshead globals
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char * command
Definition: cli.h:186
struct ast_var_t::@249 entries
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
static ast_rwlock_t globalslock

◆ load_pbx_variables()

int load_pbx_variables ( void  )

Provided by pbx_variables.c

Definition at line 1216 of file pbx_variables.c.

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

Referenced by asterisk_daemon().

1217 {
1218  int res = 0;
1219 
1224 
1225  return res;
1226 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static void unload_pbx_variables(void)
static struct ast_cli_entry vars_cli[]
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define NULL
Definition: resample.c:96
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
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 &#39;,&#39; character...
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 &#39;=&#39; character...

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

References var.

Referenced by ast_str_retrieve_variable(), ast_str_substitute_variables_full(), and pbx_substitute_variables_helper_full().

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

◆ pbx_builtin_clear_globals()

void pbx_builtin_clear_globals ( void  )

Definition at line 1191 of file pbx_variables.c.

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

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

1192 {
1193  struct ast_var_t *vardata;
1194 
1196  while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
1197  ast_var_delete(vardata);
1199 }
#define ast_rwlock_unlock(a)
Definition: lock.h:232
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2473
static struct varshead globals
struct ast_var_t::@249 entries
#define ast_rwlock_wrlock(a)
Definition: lock.h:234
static ast_rwlock_t globalslock

◆ 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"))) {
var = ast_strdupa(var);
}

Definition at line 1000 of file pbx_variables.c.

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(), globalslock, and NULL.

Referenced by __ast_pbx_run(), _if_exec(), _macro_exec(), _while_exec(), action_agents(), add_header_from_channel_var(), agent_handle_show_specific(), agent_login_channel_config(), agent_request_exec(), agent_show_requested(), aMYSQL_connect(), analog_call(), array(), ast_bridge_timelimit(), ast_bridge_transfer_attended(), ast_call_forward(), ast_channel_connected_line_macro(), ast_channel_connected_line_sub(), ast_channel_redirecting_macro(), ast_channel_redirecting_sub(), ast_eivr_getvariable(), ast_get_chan_applicationmap(), ast_monitor_stop(), ast_unreal_hangup(), attended_transfer_exec(), bridge_check_monitor(), 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(), dundi_helper(), eagi_exec(), feature_automixmonitor(), feature_automonitor(), feature_blind_transfer(), find_by_mark(), find_channel_parking_lot_name(), find_conf_realtime(), func_channel_read(), generate_parked_user(), generic_fax_exec(), get_also_info(), get_index(), get_refer_info(), get_transfer_context(), global_read(), gosub_run(), handle_call_forward(), handle_clear_alarms(), handle_gosub(), handle_hangup(), hash_read(), iax2_call(), iax2_exec(), import_ch(), leave_voicemail(), local_read(), macro_fixup(), manager_mixmonitor(), meetme_menu_admin_extended(), mgcp_call(), minivm_delete_exec(), minivm_notify_exec(), misdn_answer(), misdn_hangup(), morsecode_exec(), notify_new_message(), ooh323_call(), ooh323_hangup(), park_app_exec(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_saycharacters(), pbx_builtin_saycharacters_case(), pbx_builtin_saydigits(), pbx_builtin_saymoney(), pbx_builtin_saynumber(), pbx_builtin_sayphonetic(), pre_bridge_setup(), queue_exec(), receive_ademco_event(), report_receive_fax_status(), report_send_fax_status(), retrydial_exec(), ring_entry(), run_agi(), sayunixtime_exec(), sendtext_exec(), set_from_header(), set_local_info(), set_touch_variable(), set_transfer_variables_all(), setsubstate(), setup_mixmonitor(), setup_park_common_datastore(), sip_addheader(), sla_trunk_exec(), speech_background(), transfer_refer(), try_calling(), try_suggested_sip_codec(), and wait_for_answer().

1001 {
1002  struct ast_var_t *variables;
1003  const char *ret = NULL;
1004  int i;
1005  struct varshead *places[2] = { NULL, &globals };
1006 
1007  if (!name)
1008  return NULL;
1009 
1010  if (chan) {
1011  ast_channel_lock(chan);
1012  places[0] = ast_channel_varshead(chan);
1013  }
1014 
1015  for (i = 0; i < 2; i++) {
1016  if (!places[i])
1017  continue;
1018  if (places[i] == &globals)
1020  AST_LIST_TRAVERSE(places[i], variables, entries) {
1021  if (!strcmp(name, ast_var_name(variables))) {
1022  ret = ast_var_value(variables);
1023  break;
1024  }
1025  }
1026  if (places[i] == &globals)
1028  if (ret)
1029  break;
1030  }
1031 
1032  if (chan)
1033  ast_channel_unlock(chan);
1034 
1035  return ret;
1036 }
#define ast_rwlock_rdlock(a)
Definition: lock.h:233
#define ast_channel_lock(chan)
Definition: channel.h:2945
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
struct varshead * ast_channel_varshead(struct ast_channel *chan)
#define NULL
Definition: resample.c:96
#define ast_rwlock_unlock(a)
Definition: lock.h:232
static struct varshead globals
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static const char name[]
Definition: cdr_mysql.c:74
static ast_rwlock_t globalslock

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

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, and LOG_WARNING.

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

1039 {
1040  struct ast_var_t *newvariable;
1041  struct varshead *headp;
1042 
1043  if (name[strlen(name)-1] == ')') {
1044  char *function = ast_strdupa(name);
1045 
1046  ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
1047  ast_func_write(chan, function, value);
1048  return;
1049  }
1050 
1051  if (chan) {
1052  ast_channel_lock(chan);
1053  headp = ast_channel_varshead(chan);
1054  } else {
1056  headp = &globals;
1057  }
1058 
1059  if (value && (newvariable = ast_var_assign(name, value))) {
1060  if (headp == &globals)
1061  ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
1062  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1063  }
1064 
1065  if (chan)
1066  ast_channel_unlock(chan);
1067  else
1069 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define LOG_WARNING
Definition: logger.h:274
struct varshead * ast_channel_varshead(struct ast_channel *chan)
int value
Definition: syslog.c:37
#define ast_rwlock_unlock(a)
Definition: lock.h:232
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static struct varshead globals
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static const char name[]
Definition: cdr_mysql.c:74
#define ast_var_assign(name, value)
Definition: chanvars.h:40
#define ast_rwlock_wrlock(a)
Definition: lock.h:234
static ast_rwlock_t globalslock
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
executes a write operation on a function

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

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(), ast_var_t::entries, LOG_ERROR, total, and var.

Referenced by ast_var_channels_table(), and dumpchan_exec().

970 {
971  struct ast_var_t *variables;
972  const char *var, *val;
973  int total = 0;
974 
975  if (!chan)
976  return 0;
977 
978  ast_str_reset(*buf);
979 
980  ast_channel_lock(chan);
981 
982  AST_LIST_TRAVERSE(ast_channel_varshead(chan), variables, entries) {
983  if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
984  /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
985  ) {
986  if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
987  ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
988  break;
989  } else
990  total++;
991  } else
992  break;
993  }
994 
995  ast_channel_unlock(chan);
996 
997  return total;
998 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Definition: ast_expr2.c:325
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
#define var
Definition: ast_expr2f.c:614
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:1091
struct varshead * ast_channel_varshead(struct ast_channel *chan)
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2946
struct ast_var_t::@249 entries
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:653
static int total
Definition: res_adsi.c:968

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

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

Referenced by load_pbx_variables().

1130 {
1131  char *name, *value, *mydata;
1132 
1133  if (ast_strlen_zero(data)) {
1134  ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
1135  return 0;
1136  }
1137 
1138  mydata = ast_strdupa(data);
1139  name = strsep(&mydata, "=");
1140  value = mydata;
1141  if (!value) {
1142  ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
1143  return 0;
1144  }
1145 
1146  if (strchr(name, ' ')) {
1147  ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
1148  }
1149 
1150  pbx_builtin_setvar_helper(chan, name, value);
1151 
1152  return 0;
1153 }
#define LOG_WARNING
Definition: logger.h:274
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static const char name[]
Definition: cdr_mysql.c:74
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...
char * strsep(char **str, const char *delims)

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

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, and name.

Referenced by __analog_ss_thread(), __ast_pbx_run(), _if_exec(), _macro_exec(), _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(), aMYSQL_fetch(), aMYSQL_set(), 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_monitor_start(), ast_monitor_stop(), 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_cb(), blind_transfer_exec(), bridge_channel_internal_push_full(), bridge_exec(), bridgeadd_exec(), calendar_write_exec(), caller_joined_bridge(), caller_safety_timeout(), cb_events(), 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(), 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(), export_aoc_vars(), export_ch(), extract_transferrer_headers(), fax_detect_framehook(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_exists(), function_db_read(), function_realtime_store(), generic_recall(), get_chan_by_ast_name(), get_rdnis(), get_refer_info(), global_write(), gosub_release_frame(), gosub_run(), handle_controlstreamfile(), handle_gosub(), handle_incoming_request(), handle_outgoing_response(), handle_request_bye(), handle_response_cmgr(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), handle_streamfile(), hash_read(), hash_write(), isAnsweringMachine(), kick_conference_participant(), launch_monitor_thread(), leave_marked(), leave_queue(), leave_voicemail(), lua_set_variable(), lua_set_variable_value(), macro_fixup(), mbl_status_exec(), mgcp_new(), minivm_accmess_exec(), minivm_delete_exec(), minivm_greet_exec(), minivm_notify_exec(), minivm_record_exec(), misdn_call(), mixmonitor_exec(), msg_send_exec(), my_handle_dtmf(), MYSQL_exec(), onModeChanged(), ooh323_new(), ooh323_rtp_read(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), parking_duration_callback(), parking_timeout_set_caller_features(), parse_moved_contact(), pbx_builtin_background(), pbx_builtin_gotoiftime(), pbx_builtin_importvar(), pbx_builtin_setvar(), pbx_builtin_setvar_multiple(), pbx_builtin_waitdigit(), pbx_load_config(), phase_e_handler(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), process_ast_dsp(), process_sdp(), 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(), refer_blind_callback(), reload(), reload_module(), return_exec(), rollback_exec(), rotate_file(), rqm_exec(), select_entry(), select_item_menu(), select_item_seq(), sendfax_exec(), sendimage_exec(), sendtext_exec(), sendurl_exec(), set(), set_asterisk_int(), set_channel_variables(), set_duration_var(), set_queue_result(), set_sipdomain_variable(), setsubstate(), shift_pop(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_station_exec(), sla_trunk_exec(), speech_create(), start_automixmonitor(), start_automonitor(), start_monitor_exec(), system_exec_helper(), test_chan_variable(), testtime_write(), transfer_exec(), transmit(), tryexec_exec(), unicast_rtp_request(), unshift_push(), update_qe_rule(), upqm_exec(), user_timeout(), vm_allocate_dh(), vm_exec(), vm_playmsgexec(), vmauthenticate(), wait_exec(), wait_for_answer(), waituntil_exec(), and zapateller_exec().

1072 {
1073  struct ast_var_t *newvariable;
1074  struct varshead *headp;
1075  const char *nametail = name;
1076  /*! True if the old value was not an empty string. */
1077  int old_value_existed = 0;
1078 
1079  if (name[strlen(name) - 1] == ')') {
1080  char *function = ast_strdupa(name);
1081 
1082  return ast_func_write(chan, function, value);
1083  }
1084 
1085  if (chan) {
1086  ast_channel_lock(chan);
1087  headp = ast_channel_varshead(chan);
1088  } else {
1090  headp = &globals;
1091  }
1092 
1093  /* For comparison purposes, we have to strip leading underscores */
1094  if (*nametail == '_') {
1095  nametail++;
1096  if (*nametail == '_')
1097  nametail++;
1098  }
1099 
1100  AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1101  if (strcmp(ast_var_name(newvariable), nametail) == 0) {
1102  /* there is already such a variable, delete it */
1103  AST_LIST_REMOVE_CURRENT(entries);
1104  old_value_existed = !ast_strlen_zero(ast_var_value(newvariable));
1105  ast_var_delete(newvariable);
1106  break;
1107  }
1108  }
1110 
1111  if (value && (newvariable = ast_var_assign(name, value))) {
1112  if (headp == &globals) {
1113  ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
1114  }
1115  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1117  } else if (old_value_existed) {
1118  /* We just deleted a non-empty dialplan variable. */
1119  ast_channel_publish_varset(chan, name, "");
1120  }
1121 
1122  if (chan)
1123  ast_channel_unlock(chan);
1124  else
1126  return 0;
1127 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
struct varshead * ast_channel_varshead(struct ast_channel *chan)
int value
Definition: syslog.c:37
#define ast_rwlock_unlock(a)
Definition: lock.h:232
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
void ast_channel_publish_varset(struct ast_channel *chan, const char *variable, const char *value)
Publish a ast_channel_varset for a channel.
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2473
static struct varshead globals
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static const char name[]
Definition: cdr_mysql.c:74
#define ast_var_assign(name, value)
Definition: chanvars.h:40
#define ast_rwlock_wrlock(a)
Definition: lock.h:234
static ast_rwlock_t globalslock
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
executes a write operation on a function

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

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().

1156 {
1157  char *data;
1158  int x;
1160  AST_APP_ARG(pair)[24];
1161  );
1163  AST_APP_ARG(name);
1164  AST_APP_ARG(value);
1165  );
1166 
1167  if (ast_strlen_zero(vdata)) {
1168  ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
1169  return 0;
1170  }
1171 
1172  data = ast_strdupa(vdata);
1173  AST_STANDARD_APP_ARGS(args, data);
1174 
1175  for (x = 0; x < args.argc; x++) {
1176  AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
1177  if (pair.argc == 2) {
1178  pbx_builtin_setvar_helper(chan, pair.name, pair.value);
1179  if (strchr(pair.name, ' '))
1180  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);
1181  } else if (!chan) {
1182  ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
1183  } else {
1184  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));
1185  }
1186  }
1187 
1188  return 0;
1189 }
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
const char * args
int value
Definition: syslog.c:37
int ast_channel_priority(const struct ast_channel *chan)
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_channel_exten(const struct ast_channel *chan)
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
static const char name[]
Definition: cdr_mysql.c:74
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...
const char * name
Definition: test_config.c:85
const char * ast_channel_context(const struct ast_channel *chan)
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

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

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

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

236 {
237  struct ast_str *str = ast_str_create(16);
238  const char *cret;
239 
240  cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
241  ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
242  *ret = cret ? workspace : NULL;
243  ast_free(str);
244 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define var
Definition: ast_expr2f.c:614
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define ast_free(a)
Definition: astmm.h:182
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_str_retrieve_variable(struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ pbx_substitute_variables_helper()

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

Definition at line 835 of file pbx_variables.c.

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

836 {
837  pbx_substitute_variables_helper_full(c, (c) ? ast_channel_varshead(c) : NULL, cp1, cp2, count, NULL);
838 }
void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
struct varshead * ast_channel_varshead(struct ast_channel *chan)
#define NULL
Definition: resample.c:96

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

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, len(), LOG_ERROR, LOG_WARNING, NULL, parse_variable_name(), pbx_retrieve_variable(), substring(), var, and VAR_BUF_SIZE.

Referenced by pbx_substitute_variables_helper(), and pbx_substitute_variables_varshead().

627 {
628  /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */
629  const char *whereweare;
630  const char *orig_cp2 = cp2;
631  char ltmp[VAR_BUF_SIZE];
632  char var[VAR_BUF_SIZE];
633 
634  *cp2 = 0; /* just in case nothing ends up there */
635  whereweare = cp1;
636  while (!ast_strlen_zero(whereweare) && count) {
637  char *nextvar = NULL;
638  char *nextexp = NULL;
639  char *nextthing;
640  char *vars;
641  char *vare;
642  int length;
643  int pos;
644  int brackets;
645  int needsub;
646  int len;
647 
648  /* Determine how much simply needs to be copied to the output buf. */
649  nextthing = strchr(whereweare, '$');
650  if (nextthing) {
651  pos = nextthing - whereweare;
652  switch (nextthing[1]) {
653  case '{':
654  /* Variable substitution */
655  nextvar = nextthing;
656  break;
657  case '[':
658  /* Expression substitution */
659  nextexp = nextthing;
660  break;
661  default:
662  /* '$' is not part of a substitution so include it too. */
663  ++pos;
664  break;
665  }
666  } else {
667  /* We're copying the whole remaining string */
668  pos = strlen(whereweare);
669  }
670 
671  if (pos) {
672  /* Can't copy more than 'count' bytes */
673  if (pos > count)
674  pos = count;
675 
676  /* Copy that many bytes */
677  memcpy(cp2, whereweare, pos);
678 
679  count -= pos;
680  cp2 += pos;
681  whereweare += pos;
682  *cp2 = 0;
683  }
684 
685  if (nextvar) {
686  int offset;
687  int offset2;
688  int isfunction;
689  char *cp4;
690  char workspace[VAR_BUF_SIZE] = "";
691 
692  /* We have a variable. Find the start and end, and determine
693  if we are going to have to recursively call ourselves on the
694  contents */
695  vars = vare = nextvar + 2;
696  brackets = 1;
697  needsub = 0;
698 
699  /* Find the end of it */
700  while (brackets && *vare) {
701  if ((vare[0] == '$') && (vare[1] == '{')) {
702  needsub++;
703  brackets++;
704  vare++;
705  } else if (vare[0] == '{') {
706  brackets++;
707  } else if (vare[0] == '}') {
708  brackets--;
709  } else if ((vare[0] == '$') && (vare[1] == '[')) {
710  needsub++;
711  vare++;
712  }
713  vare++;
714  }
715  len = vare - vars;
716  if (brackets) {
717  ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
718  } else {
719  /* Don't count the closing '}' in the length. */
720  --len;
721  }
722 
723  /* Skip totally over variable string */
724  whereweare = vare;
725 
726  /* Store variable name expression to lookup (and truncate). */
727  ast_copy_string(var, vars, len + 1);
728 
729  /* Substitute if necessary */
730  if (needsub) {
731  pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, NULL);
732  vars = ltmp;
733  } else {
734  vars = var;
735  }
736 
737  parse_variable_name(vars, &offset, &offset2, &isfunction);
738  if (isfunction) {
739  /* Evaluate function */
740  if (c || !headp)
741  cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
742  else {
743  struct varshead old;
744  struct ast_channel *bogus;
745 
746  bogus = ast_dummy_channel_alloc();
747  if (bogus) {
748  old = *ast_channel_varshead(bogus);
749  *ast_channel_varshead(bogus) = *headp;
750  cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
751  /* Don't deallocate the varshead that was passed in */
752  *ast_channel_varshead(bogus) = old;
753  ast_channel_unref(bogus);
754  } else {
755  ast_log(LOG_ERROR, "Unable to allocate bogus channel for function value substitution.\n");
756  cp4 = NULL;
757  }
758  }
759  ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
760  } else {
761  /* Retrieve variable value */
762  pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
763  }
764  if (cp4) {
765  cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
766 
767  length = strlen(cp4);
768  if (length > count)
769  length = count;
770  memcpy(cp2, cp4, length);
771  count -= length;
772  cp2 += length;
773  *cp2 = 0;
774  }
775  } else if (nextexp) {
776  /* We have an expression. Find the start and end, and determine
777  if we are going to have to recursively call ourselves on the
778  contents */
779  vars = vare = nextexp + 2;
780  brackets = 1;
781  needsub = 0;
782 
783  /* Find the end of it */
784  while (brackets && *vare) {
785  if ((vare[0] == '$') && (vare[1] == '[')) {
786  needsub++;
787  brackets++;
788  vare++;
789  } else if (vare[0] == '[') {
790  brackets++;
791  } else if (vare[0] == ']') {
792  brackets--;
793  } else if ((vare[0] == '$') && (vare[1] == '{')) {
794  needsub++;
795  vare++;
796  }
797  vare++;
798  }
799  len = vare - vars;
800  if (brackets) {
801  ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
802  } else {
803  /* Don't count the closing ']' in the length. */
804  --len;
805  }
806 
807  /* Skip totally over expression */
808  whereweare = vare;
809 
810  /* Store expression to evaluate (and truncate). */
811  ast_copy_string(var, vars, len + 1);
812 
813  /* Substitute if necessary */
814  if (needsub) {
815  pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, NULL);
816  vars = ltmp;
817  } else {
818  vars = var;
819  }
820 
821  length = ast_expr(vars, cp2, count, c);
822  if (length) {
823  ast_debug(1, "Expression result is '%s'\n", cp2);
824  count -= length;
825  cp2 += length;
826  *cp2 = 0;
827  }
828  }
829  }
830  if (used) {
831  *used = cp2 - orig_cp2;
832  }
833 }
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.
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
Main Channel structure associated with a channel.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
extract offset:length from variable name.
#define LOG_WARNING
Definition: logger.h:274
#define var
Definition: ast_expr2f.c:614
void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
struct varshead * ast_channel_varshead(struct ast_channel *chan)
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1283
#define LOG_ERROR
Definition: logger.h:285
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define VAR_BUF_SIZE
Definition: pbx_private.h:68
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
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.
int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan)
Evaluate the given expression.
Definition: ast_expr2f.c:2405

◆ pbx_substitute_variables_varshead()

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

Definition at line 840 of file pbx_variables.c.

References NULL, and pbx_substitute_variables_helper_full().

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

841 {
842  pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, NULL);
843 }
void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
#define NULL
Definition: resample.c:96

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

References ast_copy_string().

Referenced by pbx_substitute_variables_helper_full().

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

◆ unload_pbx_variables()

static void unload_pbx_variables ( void  )
static

Definition at line 1208 of file pbx_variables.c.

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

Referenced by load_pbx_variables().

1209 {
1214 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static struct ast_cli_entry vars_cli[]
void pbx_builtin_clear_globals(void)
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392

Variable Documentation

◆ globals

struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
static

Definition at line 109 of file pbx_variables.c.

Referenced by pbx_builtin_pushvar_helper(), and pbx_builtin_setvar_helper().

◆ globalslock

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

◆ vars_cli

struct ast_cli_entry vars_cli[]
static

Definition at line 1201 of file pbx_variables.c.