Asterisk - The Open Source Telephony Project  GIT-master-a24979a
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_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, char *context, 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 247 of file pbx_variables.c.

248 {
249  const char not_found = '\0';
250  char *tmpvar;
251  const char *ret;
252  const char *s; /* the result */
253  int offset, length;
254  int i, need_substring;
255  struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */
256  char workspace[20];
257 
258  if (c) {
260  places[0] = ast_channel_varshead(c);
261  }
262  /*
263  * Make a copy of var because parse_variable_name() modifies the string.
264  * Then if called directly, we might need to run substring() on the result;
265  * remember this for later in 'need_substring', 'offset' and 'length'
266  */
267  tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
268  need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
269 
270  /*
271  * Look first into predefined variables, then into variable lists.
272  * Variable 's' points to the result, according to the following rules:
273  * s == &not_found (set at the beginning) means that we did not find a
274  * matching variable and need to look into more places.
275  * If s != &not_found, s is a valid result string as follows:
276  * s = NULL if the variable does not have a value;
277  * you typically do this when looking for an unset predefined variable.
278  * s = workspace if the result has been assembled there;
279  * typically done when the result is built e.g. with an snprintf(),
280  * so we don't need to do an additional copy.
281  * s != workspace in case we have a string, that needs to be copied
282  * (the ast_copy_string is done once for all at the end).
283  * Typically done when the result is already available in some string.
284  */
285  s = &not_found; /* default value */
286  if (c) { /* This group requires a valid channel */
287  /* Names with common parts are looked up a piece at a time using strncmp. */
288  if (!strncmp(var, "CALL", 4)) {
289  if (!strncmp(var + 4, "ING", 3)) {
290  if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */
291  ast_str_set(str, maxlen, "%d",
293  s = ast_str_buffer(*str);
294  } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */
295  ast_str_set(str, maxlen, "%d", ast_channel_caller(c)->ani2);
296  s = ast_str_buffer(*str);
297  } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */
298  ast_str_set(str, maxlen, "%d", ast_channel_caller(c)->id.number.plan);
299  s = ast_str_buffer(*str);
300  } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */
301  ast_str_set(str, maxlen, "%d", ast_channel_dialed(c)->transit_network_select);
302  s = ast_str_buffer(*str);
303  }
304  }
305  } else if (!strcmp(var, "HINT")) {
307  } else if (!strcmp(var, "HINTNAME")) {
309  } else if (!strcmp(var, "EXTEN")) {
310  s = ast_channel_exten(c);
311  } else if (!strcmp(var, "CONTEXT")) {
312  s = ast_channel_context(c);
313  } else if (!strcmp(var, "PRIORITY")) {
314  ast_str_set(str, maxlen, "%d", ast_channel_priority(c));
315  s = ast_str_buffer(*str);
316  } else if (!strcmp(var, "CHANNEL")) {
317  s = ast_channel_name(c);
318  } else if (!strcmp(var, "UNIQUEID")) {
319  s = ast_channel_uniqueid(c);
320  } else if (!strcmp(var, "HANGUPCAUSE")) {
321  ast_str_set(str, maxlen, "%d", ast_channel_hangupcause(c));
322  s = ast_str_buffer(*str);
323  }
324  }
325  if (s == &not_found) { /* look for more */
326  if (!strcmp(var, "EPOCH")) {
327  ast_str_set(str, maxlen, "%d", (int) time(NULL));
328  s = ast_str_buffer(*str);
329  } else if (!strcmp(var, "SYSTEMNAME")) {
331  } else if (!strcmp(var, "ASTCACHEDIR")) {
333  } else if (!strcmp(var, "ASTETCDIR")) {
335  } else if (!strcmp(var, "ASTMODDIR")) {
337  } else if (!strcmp(var, "ASTVARLIBDIR")) {
339  } else if (!strcmp(var, "ASTDBDIR")) {
340  s = ast_config_AST_DB;
341  } else if (!strcmp(var, "ASTKEYDIR")) {
343  } else if (!strcmp(var, "ASTDATADIR")) {
345  } else if (!strcmp(var, "ASTAGIDIR")) {
347  } else if (!strcmp(var, "ASTSPOOLDIR")) {
349  } else if (!strcmp(var, "ASTRUNDIR")) {
351  } else if (!strcmp(var, "ASTLOGDIR")) {
353  } else if (!strcmp(var, "ASTSBINDIR")) {
355  } else if (!strcmp(var, "ENTITYID")) {
356  ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
357  s = workspace;
358  }
359  }
360  /* if not found, look into chanvars or global vars */
361  for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
362  struct ast_var_t *variables;
363  if (!places[i])
364  continue;
365  if (places[i] == &globals)
367  AST_LIST_TRAVERSE(places[i], variables, entries) {
368  if (!strcmp(ast_var_name(variables), var)) {
369  s = ast_var_value(variables);
370  break;
371  }
372  }
373  if (places[i] == &globals)
375  }
376  if (s == &not_found || s == NULL) {
377  ast_debug(5, "Result of '%s' is NULL\n", var);
378  ret = NULL;
379  } else {
380  ast_debug(5, "Result of '%s' is '%s'\n", var, s);
381  if (s != ast_str_buffer(*str)) {
382  ast_str_set(str, maxlen, "%s", s);
383  }
384  ret = ast_str_buffer(*str);
385  if (need_substring) {
386  ret = ast_str_substring(*str, offset, length);
387  ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
388  }
389  }
390 
391  if (c) {
393  }
394  return ret;
395 }
const char * str
Definition: app_jack.c:147
#define var
Definition: ast_expr2f.c:614
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:1815
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2922
const char * ast_channel_context(const struct ast_channel *chan)
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_hangupcause(const struct ast_channel *chan)
const char * ast_channel_exten(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
struct varshead * ast_channel_varshead(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:233
#define ast_rwlock_unlock(a)
Definition: lock.h:232
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:4162
static ast_rwlock_t globalslock
static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
extract offset:length from variable name.
static const char * ast_str_substring(struct ast_str *value, int offset, int length)
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:739
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:1091
struct ast_var_t::@239 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: main/utils.c:2735
#define ARRAY_LEN(a)
Definition: utils.h:661
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_full(), 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 619 of file pbx_variables.c.

620 {
621  ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, NULL);
622 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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)

References ast_str_substitute_variables_full(), buf, and NULL.

Referenced by _macro_exec(), acf_odbc_read(), acf_odbc_write(), AST_TEST_DEFINE(), cli_odbc_read(), config_curl(), custom_log(), cut_internal(), destroy_curl(), do_notify(), exec_exec(), func_mchan_read(), 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(), store_curl(), strbetween(), strreplace(), test_2way_function(), tryexec_exec(), 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 397 of file pbx_variables.c.

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

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_full(), ast_str_substring(), ast_strlen_zero(), buf, c, len(), LOG_ERROR, LOG_WARNING, NULL, and parse_variable_name().

Referenced by ast_str_substitute_variables(), ast_str_substitute_variables_full(), and ast_str_substitute_variables_varshead().

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

625 {
626  ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, NULL);
627 }

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

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

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

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

932 {
933  struct ast_channel *c = NULL;
934  char *fn, *substituted;
935  int ret;
936  char workspace[1024];
937 
938  switch (cmd) {
939  case CLI_INIT:
940  e->command = "dialplan eval function";
941  e->usage =
942  "Usage: dialplan eval function <name(args)>\n"
943  " Evaluate a dialplan function call\n"
944  " A dummy channel is used to evaluate\n"
945  " the function call, so only global\n"
946  " variables should be used.\n";
947  return NULL;
948  case CLI_GENERATE:
949  return NULL;
950  }
951 
952  if (a->argc != e->args + 1) {
953  return CLI_SHOWUSAGE;
954  }
955 
957  if (!c) {
958  ast_cli(a->fd, "Unable to allocate bogus channel for function evaluation.\n");
959  return CLI_FAILURE;
960  }
961 
962  fn = (char *) a->argv[3];
963  pbx_substitute_variables_helper(c, fn, workspace, sizeof(workspace));
964  substituted = ast_strdupa(workspace);
965  workspace[0] = '\0';
966  ret = ast_func_read(c, substituted, workspace, sizeof(workspace));
967 
968  c = ast_channel_unref(c);
969 
970  ast_cli(a->fd, "Return Value: %s (%d)\n", ret ? "Failure" : "Success", ret);
971  ast_cli(a->fd, "Result: %s\n", workspace);
972 
973  return CLI_SUCCESS;
974 }
#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 998 of file pbx_variables.c.

999 {
1000  struct ast_channel *chan;
1001  const char *chan_name, *var_name, *var_value;
1002 
1003  switch (cmd) {
1004  case CLI_INIT:
1005  e->command = "dialplan set chanvar";
1006  e->usage =
1007  "Usage: dialplan set chanvar <channel> <varname> <value>\n"
1008  " Set channel variable <varname> to <value>\n";
1009  return NULL;
1010  case CLI_GENERATE:
1011  return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
1012  }
1013 
1014  if (a->argc != e->args + 3)
1015  return CLI_SHOWUSAGE;
1016 
1017  chan_name = a->argv[e->args];
1018  var_name = a->argv[e->args + 1];
1019  var_value = a->argv[e->args + 2];
1020 
1021  if (!(chan = ast_channel_get_by_name(chan_name))) {
1022  ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
1023  return CLI_FAILURE;
1024  }
1025 
1026  pbx_builtin_setvar_helper(chan, var_name, var_value);
1027 
1028  chan = ast_channel_unref(chan);
1029 
1030  ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name);
1031 
1032  return CLI_SUCCESS;
1033 }
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 976 of file pbx_variables.c.

977 {
978  switch (cmd) {
979  case CLI_INIT:
980  e->command = "dialplan set global";
981  e->usage =
982  "Usage: dialplan set global <name> <value>\n"
983  " Set global dialplan variable <name> to <value>\n";
984  return NULL;
985  case CLI_GENERATE:
986  return NULL;
987  }
988 
989  if (a->argc != e->args + 2)
990  return CLI_SHOWUSAGE;
991 
992  pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
993  ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
994 
995  return CLI_SUCCESS;
996 }

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

895 {
896  struct ast_channel *chan;
897  struct ast_var_t *var;
898 
899  switch (cmd) {
900  case CLI_INIT:
901  e->command = "dialplan show chanvar";
902  e->usage =
903  "Usage: dialplan show chanvar <channel>\n"
904  " List current channel variables and their values\n";
905  return NULL;
906  case CLI_GENERATE:
907  return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
908  }
909 
910  if (a->argc != e->args + 1) {
911  return CLI_SHOWUSAGE;
912  }
913 
914  chan = ast_channel_get_by_name(a->argv[e->args]);
915  if (!chan) {
916  ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
917  return CLI_FAILURE;
918  }
919 
920  ast_channel_lock(chan);
922  ast_cli(a->fd, "%s=%s\n", ast_var_name(var), ast_var_value(var));
923  }
924  ast_channel_unlock(chan);
925 
926  ast_channel_unref(chan);
927  return CLI_SUCCESS;
928 }

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

867 {
868  int i = 0;
869  struct ast_var_t *newvariable;
870 
871  switch (cmd) {
872  case CLI_INIT:
873  e->command = "dialplan show globals";
874  e->usage =
875  "Usage: dialplan show globals\n"
876  " List current global dialplan variables and their values\n";
877  return NULL;
878  case CLI_GENERATE:
879  return NULL;
880  }
881 
883  AST_LIST_TRAVERSE (&globals, newvariable, entries) {
884  i++;
885  ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
886  }
888  ast_cli(a->fd, "\n -- %d variable(s)\n", i);
889 
890  return CLI_SUCCESS;
891 }

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

1284 {
1285  int res = 0;
1286 
1291 
1292  return res;
1293 }
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,...

References ARRAY_LEN, ast_cli_register_multiple, ast_register_application2(), ast_register_cleanup(), 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 117 of file pbx_variables.c.

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

References var.

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

◆ pbx_builtin_clear_globals()

void pbx_builtin_clear_globals ( void  )

Definition at line 1257 of file pbx_variables.c.

1258 {
1259  struct ast_var_t *vardata;
1260 
1262  while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
1263  ast_var_delete(vardata);
1265 }
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2472
#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:234

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

Referenced by 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 1066 of file pbx_variables.c.

1067 {
1068  struct ast_var_t *variables;
1069  const char *ret = NULL;
1070  int i;
1071  struct varshead *places[2] = { NULL, &globals };
1072 
1073  if (!name)
1074  return NULL;
1075 
1076  if (chan) {
1077  ast_channel_lock(chan);
1078  places[0] = ast_channel_varshead(chan);
1079  }
1080 
1081  for (i = 0; i < 2; i++) {
1082  if (!places[i])
1083  continue;
1084  if (places[i] == &globals)
1086  AST_LIST_TRAVERSE(places[i], variables, entries) {
1087  if (!strcmp(name, ast_var_name(variables))) {
1088  ret = ast_var_value(variables);
1089  break;
1090  }
1091  }
1092  if (places[i] == &globals)
1094  if (ret)
1095  break;
1096  }
1097 
1098  if (chan)
1099  ast_channel_unlock(chan);
1100 
1101  return ret;
1102 }
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 _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(), analog_call(), array(), ast_bridge_timelimit(), 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(), 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(), handle_call_forward(), handle_hangup(), iax2_call(), iax2_exec(), leave_voicemail(), macro_fixup(), manager_mixmonitor(), meetme_menu_admin_extended(), mgcp_call(), minivm_delete_exec(), minivm_notify_exec(), morsecode_exec(), notify_new_message(), ooh323_call(), ooh323_hangup(), park_app_exec(), pbx_builtin_background(), pbx_builtin_gotoiftime(), permit_dtmf_interrupt(), pre_bridge_setup(), queue_exec(), receive_ademco_event(), report_receive_fax_status(), report_send_fax_status(), retrydial_exec(), ring_entry(), sayunixtime_exec(), sendtext_exec(), set_from_header(), set_touch_variable(), set_transfer_variables_all(), setsubstate(), setup_mixmonitor(), setup_park_common_datastore(), sip_addheader(), sla_state(), speech_background(), transfer_refer(), try_calling(), try_suggested_sip_codec(), 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 1104 of file pbx_variables.c.

1105 {
1106  struct ast_var_t *newvariable;
1107  struct varshead *headp;
1108 
1109  if (name[strlen(name)-1] == ')') {
1110  char *function = ast_strdupa(name);
1111 
1112  ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
1113  ast_func_write(chan, function, value);
1114  return;
1115  }
1116 
1117  if (chan) {
1118  ast_channel_lock(chan);
1119  headp = ast_channel_varshead(chan);
1120  } else {
1122  headp = &globals;
1123  }
1124 
1125  if (value && (newvariable = ast_var_assign(name, value))) {
1126  if (headp == &globals)
1127  ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
1128  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1129  }
1130 
1131  if (chan)
1132  ast_channel_unlock(chan);
1133  else
1135 }
#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(), 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 1035 of file pbx_variables.c.

1036 {
1037  struct ast_var_t *variables;
1038  const char *var, *val;
1039  int total = 0;
1040 
1041  if (!chan)
1042  return 0;
1043 
1044  ast_str_reset(*buf);
1045 
1046  ast_channel_lock(chan);
1047 
1048  AST_LIST_TRAVERSE(ast_channel_varshead(chan), variables, entries) {
1049  if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
1050  /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
1051  ) {
1052  if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
1053  ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
1054  break;
1055  } else
1056  total++;
1057  } else
1058  break;
1059  }
1060 
1061  ast_channel_unlock(chan);
1062 
1063  return total;
1064 }
static int total
Definition: res_adsi.c:968
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 1195 of file pbx_variables.c.

1196 {
1197  char *name, *value, *mydata;
1198 
1199  if (ast_strlen_zero(data)) {
1200  ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
1201  return 0;
1202  }
1203 
1204  mydata = ast_strdupa(data);
1205  name = strsep(&mydata, "=");
1206  value = mydata;
1207  if (!value) {
1208  ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
1209  return 0;
1210  }
1211 
1212  if (strchr(name, ' ')) {
1213  ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
1214  }
1215 
1217 
1218  return 0;
1219 }
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 1137 of file pbx_variables.c.

1138 {
1139  struct ast_var_t *newvariable;
1140  struct varshead *headp;
1141  const char *nametail = name;
1142  /*! True if the old value was not an empty string. */
1143  int old_value_existed = 0;
1144 
1145  if (name[strlen(name) - 1] == ')') {
1146  char *function = ast_strdupa(name);
1147 
1148  return ast_func_write(chan, function, value);
1149  }
1150 
1151  if (chan) {
1152  ast_channel_lock(chan);
1153  headp = ast_channel_varshead(chan);
1154  } else {
1156  headp = &globals;
1157  }
1158 
1159  /* For comparison purposes, we have to strip leading underscores */
1160  if (*nametail == '_') {
1161  nametail++;
1162  if (*nametail == '_')
1163  nametail++;
1164  }
1165 
1166  AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1167  if (strcmp(ast_var_name(newvariable), nametail) == 0) {
1168  /* there is already such a variable, delete it */
1169  AST_LIST_REMOVE_CURRENT(entries);
1170  old_value_existed = !ast_strlen_zero(ast_var_value(newvariable));
1171  ast_var_delete(newvariable);
1172  break;
1173  }
1174  }
1176 
1177  if (value && (newvariable = ast_var_assign(name, value))) {
1178  if (headp == &globals) {
1179  ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
1180  }
1181  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1183  } else if (old_value_existed) {
1184  /* We just deleted a non-empty dialplan variable. */
1185  ast_channel_publish_varset(chan, name, "");
1186  }
1187 
1188  if (chan)
1189  ast_channel_unlock(chan);
1190  else
1192  return 0;
1193 }
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(), _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(), 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_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_exec(), audiosocket_request(), background_detect_exec(), begin_dial_channel(), blind_transfer_cb(), 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(), 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(), extract_transferrer_headers(), fax_detect_framehook(), frame_set_var(), func_mchan_write(), function_db_delete(), function_db_read(), function_realtime_store(), generic_recall(), get_destination(), get_refer_info(), gosub_release_frame(), handle_controlstreamfile(), handle_incoming_request(), handle_outgoing_response(), handle_request_bye(), handle_response_cmgr(), handle_set_chanvar(), handle_set_global(), handle_setvariable(), handle_streamfile(), 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(), mixmonitor_exec(), msg_send_exec(), my_handle_dtmf(), 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(), play_message_datetime(), playback_exec(), pqm_exec(), prep_email_sub_vars(), privacy_exec(), 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(), recvtext_exec(), refer_blind_callback(), reload_exec(), reload_module(), return_exec(), ring_entry(), rollback_exec(), rotate_file(), rqm_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(), setsubstate(), sip_addheader(), sip_hangup(), sip_new(), sip_read(), skinny_new(), sla_calc_trunk_timeouts(), sla_state(), sla_station_exec(), speech_create(), start_automixmonitor(), start_automonitor(), start_monitor_exec(), system_exec_helper(), transfer_exec(), tryexec_exec(), unicast_rtp_request(), update_qe_rule(), upqm_exec(), user_timeout(), vm_exec(), vm_playmsgexec(), vmauthenticate(), wait_exec(), wait_for_answer(), waitforcond_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 1221 of file pbx_variables.c.

1222 {
1223  char *data;
1224  int x;
1226  AST_APP_ARG(pair)[99]; /* parse up to 99 variables */
1227  );
1229  AST_APP_ARG(name);
1230  AST_APP_ARG(value);
1231  );
1232 
1233  if (ast_strlen_zero(vdata)) {
1234  ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
1235  return 0;
1236  }
1237 
1238  data = ast_strdupa(vdata);
1239  AST_STANDARD_APP_ARGS(args, data);
1240 
1241  for (x = 0; x < args.argc; x++) {
1242  AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
1243  if (pair.argc == 2) {
1244  pbx_builtin_setvar_helper(chan, pair.name, pair.value);
1245  if (strchr(pair.name, ' '))
1246  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);
1247  } else if (!chan) {
1248  ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
1249  } else {
1250  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));
1251  }
1252  }
1253 
1254  return 0;
1255 }
#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 236 of file pbx_variables.c.

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

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

856 {
858 }
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 629 of file pbx_variables.c.

630 {
631  pbx_substitute_variables_helper_full_location(c, headp, cp1, cp2, count, used, NULL, NULL, 0);
632 }
void pbx_substitute_variables_helper_full_location(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used, char *context, 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,
char *  context,
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 634 of file pbx_variables.c.

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

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, context, 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 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 860 of file pbx_variables.c.

861 {
862  pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, NULL);
863 }

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

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

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

1276 {
1281 }
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)

References ARRAY_LEN, ast_cli_unregister_multiple(), 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 1257 of file pbx_variables.c.

Referenced by load_pbx_variables(), and unload_pbx_variables().