Asterisk - The Open Source Telephony Project  GIT-master-1f78ee9
pbx_variables.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2016, CFWare, LLC
5  *
6  * Corey Farrell <git@cfware.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief PBX variables routines.
22  *
23  * \author Corey Farrell <git@cfware.com>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 #include "asterisk/_private.h"
33 #include "asterisk/app.h"
34 #include "asterisk/ast_expr.h"
35 #include "asterisk/chanvars.h"
36 #include "asterisk/cli.h"
37 #include "asterisk/linkedlists.h"
38 #include "asterisk/lock.h"
39 #include "asterisk/module.h"
40 #include "asterisk/paths.h"
41 #include "asterisk/pbx.h"
43 #include "pbx_private.h"
44 
45 /*** DOCUMENTATION
46  <application name="Set" language="en_US">
47  <synopsis>
48  Set channel variable or function value.
49  </synopsis>
50  <syntax argsep="=">
51  <parameter name="name" required="true" />
52  <parameter name="value" required="true" />
53  </syntax>
54  <description>
55  <para>This function can be used to set the value of channel variables or dialplan functions.
56  When setting variables, if the variable name is prefixed with <literal>_</literal>,
57  the variable will be inherited into channels created from the current channel.
58  If the variable name is prefixed with <literal>__</literal>, the variable will be
59  inherited into channels created from the current channel and all children channels.</para>
60  <note><para>If (and only if), in <filename>/etc/asterisk/asterisk.conf</filename>, you have
61  a <literal>[compat]</literal> category, and you have <literal>app_set = 1.4</literal> under that, then
62  the behavior of this app changes, and strips surrounding quotes from the right hand side as
63  it did previously in 1.4.
64  The advantages of not stripping out quoting, and not caring about the separator characters (comma and vertical bar)
65  were sufficient to make these changes in 1.6. Confusion about how many backslashes would be needed to properly
66  protect separators and quotes in various database access strings has been greatly
67  reduced by these changes.</para></note>
68  </description>
69  <see-also>
70  <ref type="application">MSet</ref>
71  <ref type="function">GLOBAL</ref>
72  <ref type="function">SET</ref>
73  <ref type="function">ENV</ref>
74  </see-also>
75  </application>
76  <application name="MSet" language="en_US">
77  <synopsis>
78  Set channel variable(s) or function value(s).
79  </synopsis>
80  <syntax>
81  <parameter name="set1" required="true" argsep="=">
82  <argument name="name1" required="true" />
83  <argument name="value1" required="true" />
84  </parameter>
85  <parameter name="set2" multiple="true" argsep="=">
86  <argument name="name2" required="true" />
87  <argument name="value2" required="true" />
88  </parameter>
89  </syntax>
90  <description>
91  <para>This function can be used to set the value of channel variables or dialplan functions.
92  When setting variables, if the variable name is prefixed with <literal>_</literal>,
93  the variable will be inherited into channels created from the current channel
94  If the variable name is prefixed with <literal>__</literal>, the variable will be
95  inherited into channels created from the current channel and all children channels.
96  MSet behaves in a similar fashion to the way Set worked in 1.2/1.4 and is thus
97  prone to doing things that you may not expect. For example, it strips surrounding
98  double-quotes from the right-hand side (value). If you need to put a separator
99  character (comma or vert-bar), you will need to escape them by inserting a backslash
100  before them. Avoid its use if possible.</para>
101  </description>
102  <see-also>
103  <ref type="application">Set</ref>
104  </see-also>
105  </application>
106  ***/
107 
110 
111 /*!
112  * \brief extract offset:length from variable name.
113  * \return 1 if there is a offset:length part, which is
114  * trimmed off (values go into variables)
115  */
116 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
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 }
137 
138 /*!
139  *\brief takes a substring. It is ok to call with value == workspace.
140  * \param value
141  * \param offset < 0 means start from the end of the string and set the beginning
142  * to be that many characters back.
143  * \param length is the length of the substring, a value less than 0 means to leave
144  * that many off the end.
145  * \param workspace
146  * \param workspace_len
147  * Always return a copy in workspace.
148  */
149 static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
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 }
184 
185 static const char *ast_str_substring(struct ast_str *value, int offset, int length)
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 }
228 
229 /*! \brief Support for Asterisk built-in variables in the dialplan
230 
231 \note See also
232  - \ref AstVar Channel variables
233  - \ref AstCauses The HANGUPCAUSE variable
234  */
235 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
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 }
245 
246 const char *ast_str_retrieve_variable(struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
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, "ASTETCDIR")) {
332  } else if (!strcmp(var, "ASTMODDIR")) {
334  } else if (!strcmp(var, "ASTVARLIBDIR")) {
336  } else if (!strcmp(var, "ASTDBDIR")) {
337  s = ast_config_AST_DB;
338  } else if (!strcmp(var, "ASTKEYDIR")) {
340  } else if (!strcmp(var, "ASTDATADIR")) {
342  } else if (!strcmp(var, "ASTAGIDIR")) {
344  } else if (!strcmp(var, "ASTSPOOLDIR")) {
346  } else if (!strcmp(var, "ASTRUNDIR")) {
348  } else if (!strcmp(var, "ASTLOGDIR")) {
350  } else if (!strcmp(var, "ENTITYID")) {
351  ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
352  s = workspace;
353  }
354  }
355  /* if not found, look into chanvars or global vars */
356  for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
357  struct ast_var_t *variables;
358  if (!places[i])
359  continue;
360  if (places[i] == &globals)
362  AST_LIST_TRAVERSE(places[i], variables, entries) {
363  if (!strcmp(ast_var_name(variables), var)) {
364  s = ast_var_value(variables);
365  break;
366  }
367  }
368  if (places[i] == &globals)
370  }
371  if (s == &not_found || s == NULL) {
372  ast_debug(5, "Result of '%s' is NULL\n", var);
373  ret = NULL;
374  } else {
375  ast_debug(5, "Result of '%s' is '%s'\n", var, s);
376  if (s != ast_str_buffer(*str)) {
377  ast_str_set(str, maxlen, "%s", s);
378  }
379  ret = ast_str_buffer(*str);
380  if (need_substring) {
381  ret = ast_str_substring(*str, offset, length);
382  ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
383  }
384  }
385 
386  if (c) {
388  }
389  return ret;
390 }
391 
392 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)
393 {
394  /* Substitutes variables into buf, based on string templ */
395  const char *whereweare;
396  struct ast_str *substr1 = ast_str_create(16);
397  struct ast_str *substr2 = NULL;
398  struct ast_str *substr3 = ast_str_create(16);
399 
400  ast_str_reset(*buf);
401 
402  if (!substr1 || !substr3) {
403  if (used) {
404  *used = ast_str_strlen(*buf);
405  }
406  ast_free(substr1);
407  ast_free(substr3);
408  return;
409  }
410 
411  whereweare = templ;
412  while (!ast_strlen_zero(whereweare)) {
413  const char *nextvar = NULL;
414  const char *nextexp = NULL;
415  const char *nextthing;
416  const char *vars;
417  const char *vare;
418  char *finalvars;
419  int pos;
420  int brackets;
421  int needsub;
422  int len;
423 
424  /* reset our buffer */
425  ast_str_reset(substr3);
426 
427  /* Determine how much simply needs to be copied to the output buf. */
428  nextthing = strchr(whereweare, '$');
429  if (nextthing) {
430  pos = nextthing - whereweare;
431  switch (nextthing[1]) {
432  case '{':
433  /* Variable substitution */
434  nextvar = nextthing;
435  break;
436  case '[':
437  /* Expression substitution */
438  nextexp = nextthing;
439  break;
440  default:
441  /* '$' is not part of a substitution so include it too. */
442  ++pos;
443  break;
444  }
445  } else {
446  /* We're copying the whole remaining string */
447  pos = strlen(whereweare);
448  }
449 
450  if (pos) {
451  /* Copy that many bytes */
452  ast_str_append_substr(buf, maxlen, whereweare, pos);
453 
454  whereweare += pos;
455  }
456 
457  if (nextvar) {
458  int offset;
459  int offset2;
460  int isfunction;
461  int res;
462 
463  /* We have a variable. Find the start and end, and determine
464  if we are going to have to recursively call ourselves on the
465  contents */
466  vars = vare = nextvar + 2;
467  brackets = 1;
468  needsub = 0;
469 
470  /* Find the end of it */
471  while (brackets && *vare) {
472  if ((vare[0] == '$') && (vare[1] == '{')) {
473  needsub++;
474  brackets++;
475  vare++;
476  } else if (vare[0] == '{') {
477  brackets++;
478  } else if (vare[0] == '}') {
479  brackets--;
480  } else if ((vare[0] == '$') && (vare[1] == '[')) {
481  needsub++;
482  vare++;
483  }
484  vare++;
485  }
486  len = vare - vars;
487  if (brackets) {
488  ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
489  } else {
490  /* Don't count the closing '}' in the length. */
491  --len;
492  }
493 
494  /* Skip totally over variable string */
495  whereweare = vare;
496 
497  /* Store variable name expression to lookup. */
498  ast_str_set_substr(&substr1, 0, vars, len);
499  ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
500 
501  /* Substitute if necessary */
502  if (needsub) {
503  if (!substr2) {
504  substr2 = ast_str_create(16);
505  if (!substr2) {
506  continue;
507  }
508  }
509  ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), NULL);
510  finalvars = ast_str_buffer(substr2);
511  } else {
512  finalvars = ast_str_buffer(substr1);
513  }
514 
515  parse_variable_name(finalvars, &offset, &offset2, &isfunction);
516  if (isfunction) {
517  /* Evaluate function */
518  if (c || !headp) {
519  res = ast_func_read2(c, finalvars, &substr3, 0);
520  } else {
521  struct varshead old;
522  struct ast_channel *bogus;
523 
524  bogus = ast_dummy_channel_alloc();
525  if (bogus) {
526  old = *ast_channel_varshead(bogus);
527  *ast_channel_varshead(bogus) = *headp;
528  res = ast_func_read2(bogus, finalvars, &substr3, 0);
529  /* Don't deallocate the varshead that was passed in */
530  *ast_channel_varshead(bogus) = old;
531  ast_channel_unref(bogus);
532  } else {
533  ast_log(LOG_ERROR, "Unable to allocate bogus channel for function value substitution.\n");
534  res = -1;
535  }
536  }
537  ast_debug(2, "Function %s result is '%s'\n",
538  finalvars, res ? "" : ast_str_buffer(substr3));
539  } else {
540  /* Retrieve variable value */
541  ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
542  res = 0;
543  }
544  if (!res) {
545  ast_str_substring(substr3, offset, offset2);
546  ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
547  }
548  } else if (nextexp) {
549  /* We have an expression. Find the start and end, and determine
550  if we are going to have to recursively call ourselves on the
551  contents */
552  vars = vare = nextexp + 2;
553  brackets = 1;
554  needsub = 0;
555 
556  /* Find the end of it */
557  while (brackets && *vare) {
558  if ((vare[0] == '$') && (vare[1] == '[')) {
559  needsub++;
560  brackets++;
561  vare++;
562  } else if (vare[0] == '[') {
563  brackets++;
564  } else if (vare[0] == ']') {
565  brackets--;
566  } else if ((vare[0] == '$') && (vare[1] == '{')) {
567  needsub++;
568  vare++;
569  }
570  vare++;
571  }
572  len = vare - vars;
573  if (brackets) {
574  ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
575  } else {
576  /* Don't count the closing ']' in the length. */
577  --len;
578  }
579 
580  /* Skip totally over expression */
581  whereweare = vare;
582 
583  /* Store expression to evaluate. */
584  ast_str_set_substr(&substr1, 0, vars, len);
585 
586  /* Substitute if necessary */
587  if (needsub) {
588  if (!substr2) {
589  substr2 = ast_str_create(16);
590  if (!substr2) {
591  continue;
592  }
593  }
594  ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), NULL);
595  finalvars = ast_str_buffer(substr2);
596  } else {
597  finalvars = ast_str_buffer(substr1);
598  }
599 
600  if (ast_str_expr(&substr3, 0, c, finalvars)) {
601  ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
602  }
603  ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
604  }
605  }
606  if (used) {
607  *used = ast_str_strlen(*buf);
608  }
609  ast_free(substr1);
610  ast_free(substr2);
611  ast_free(substr3);
612 }
613 
614 void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
615 {
616  ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, NULL);
617 }
618 
619 void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
620 {
621  ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, NULL);
622 }
623 
624 void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
625 {
626  /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */
627  const char *whereweare;
628  const char *orig_cp2 = cp2;
629  char ltmp[VAR_BUF_SIZE];
630  char var[VAR_BUF_SIZE];
631 
632  *cp2 = 0; /* just in case nothing ends up there */
633  whereweare = cp1;
634  while (!ast_strlen_zero(whereweare) && count) {
635  char *nextvar = NULL;
636  char *nextexp = NULL;
637  char *nextthing;
638  char *vars;
639  char *vare;
640  int length;
641  int pos;
642  int brackets;
643  int needsub;
644  int len;
645 
646  /* Determine how much simply needs to be copied to the output buf. */
647  nextthing = strchr(whereweare, '$');
648  if (nextthing) {
649  pos = nextthing - whereweare;
650  switch (nextthing[1]) {
651  case '{':
652  /* Variable substitution */
653  nextvar = nextthing;
654  break;
655  case '[':
656  /* Expression substitution */
657  nextexp = nextthing;
658  break;
659  default:
660  /* '$' is not part of a substitution so include it too. */
661  ++pos;
662  break;
663  }
664  } else {
665  /* We're copying the whole remaining string */
666  pos = strlen(whereweare);
667  }
668 
669  if (pos) {
670  /* Can't copy more than 'count' bytes */
671  if (pos > count)
672  pos = count;
673 
674  /* Copy that many bytes */
675  memcpy(cp2, whereweare, pos);
676 
677  count -= pos;
678  cp2 += pos;
679  whereweare += pos;
680  *cp2 = 0;
681  }
682 
683  if (nextvar) {
684  int offset;
685  int offset2;
686  int isfunction;
687  char *cp4;
688  char workspace[VAR_BUF_SIZE] = "";
689 
690  /* We have a variable. Find the start and end, and determine
691  if we are going to have to recursively call ourselves on the
692  contents */
693  vars = vare = nextvar + 2;
694  brackets = 1;
695  needsub = 0;
696 
697  /* Find the end of it */
698  while (brackets && *vare) {
699  if ((vare[0] == '$') && (vare[1] == '{')) {
700  needsub++;
701  brackets++;
702  vare++;
703  } else if (vare[0] == '{') {
704  brackets++;
705  } else if (vare[0] == '}') {
706  brackets--;
707  } else if ((vare[0] == '$') && (vare[1] == '[')) {
708  needsub++;
709  vare++;
710  }
711  vare++;
712  }
713  len = vare - vars;
714  if (brackets) {
715  ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
716  } else {
717  /* Don't count the closing '}' in the length. */
718  --len;
719  }
720 
721  /* Skip totally over variable string */
722  whereweare = vare;
723 
724  /* Store variable name expression to lookup (and truncate). */
725  ast_copy_string(var, vars, len + 1);
726 
727  /* Substitute if necessary */
728  if (needsub) {
729  pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, NULL);
730  vars = ltmp;
731  } else {
732  vars = var;
733  }
734 
735  parse_variable_name(vars, &offset, &offset2, &isfunction);
736  if (isfunction) {
737  /* Evaluate function */
738  if (c || !headp)
739  cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
740  else {
741  struct varshead old;
742  struct ast_channel *bogus;
743 
744  bogus = ast_dummy_channel_alloc();
745  if (bogus) {
746  old = *ast_channel_varshead(bogus);
747  *ast_channel_varshead(bogus) = *headp;
748  cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
749  /* Don't deallocate the varshead that was passed in */
750  *ast_channel_varshead(bogus) = old;
751  ast_channel_unref(bogus);
752  } else {
753  ast_log(LOG_ERROR, "Unable to allocate bogus channel for function value substitution.\n");
754  cp4 = NULL;
755  }
756  }
757  ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
758  } else {
759  /* Retrieve variable value */
760  pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
761  }
762  if (cp4) {
763  cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
764 
765  length = strlen(cp4);
766  if (length > count)
767  length = count;
768  memcpy(cp2, cp4, length);
769  count -= length;
770  cp2 += length;
771  *cp2 = 0;
772  }
773  } else if (nextexp) {
774  /* We have an expression. Find the start and end, and determine
775  if we are going to have to recursively call ourselves on the
776  contents */
777  vars = vare = nextexp + 2;
778  brackets = 1;
779  needsub = 0;
780 
781  /* Find the end of it */
782  while (brackets && *vare) {
783  if ((vare[0] == '$') && (vare[1] == '[')) {
784  needsub++;
785  brackets++;
786  vare++;
787  } else if (vare[0] == '[') {
788  brackets++;
789  } else if (vare[0] == ']') {
790  brackets--;
791  } else if ((vare[0] == '$') && (vare[1] == '{')) {
792  needsub++;
793  vare++;
794  }
795  vare++;
796  }
797  len = vare - vars;
798  if (brackets) {
799  ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
800  } else {
801  /* Don't count the closing ']' in the length. */
802  --len;
803  }
804 
805  /* Skip totally over expression */
806  whereweare = vare;
807 
808  /* Store expression to evaluate (and truncate). */
809  ast_copy_string(var, vars, len + 1);
810 
811  /* Substitute if necessary */
812  if (needsub) {
813  pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, NULL);
814  vars = ltmp;
815  } else {
816  vars = var;
817  }
818 
819  length = ast_expr(vars, cp2, count, c);
820  if (length) {
821  ast_debug(1, "Expression result is '%s'\n", cp2);
822  count -= length;
823  cp2 += length;
824  *cp2 = 0;
825  }
826  }
827  }
828  if (used) {
829  *used = cp2 - orig_cp2;
830  }
831 }
832 
833 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
834 {
835  pbx_substitute_variables_helper_full(c, (c) ? ast_channel_varshead(c) : NULL, cp1, cp2, count, NULL);
836 }
837 
838 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
839 {
840  pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, NULL);
841 }
842 
843 /*! \brief CLI support for listing global variables in a parseable way */
844 static char *handle_show_globals(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
845 {
846  int i = 0;
847  struct ast_var_t *newvariable;
848 
849  switch (cmd) {
850  case CLI_INIT:
851  e->command = "dialplan show globals";
852  e->usage =
853  "Usage: dialplan show globals\n"
854  " List current global dialplan variables and their values\n";
855  return NULL;
856  case CLI_GENERATE:
857  return NULL;
858  }
859 
861  AST_LIST_TRAVERSE (&globals, newvariable, entries) {
862  i++;
863  ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
864  }
866  ast_cli(a->fd, "\n -- %d variable(s)\n", i);
867 
868  return CLI_SUCCESS;
869 }
870 
871 /*! \brief CLI support for listing chanvar's variables in a parseable way */
872 static char *handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
873 {
874  struct ast_channel *chan;
875  struct ast_var_t *var;
876 
877  switch (cmd) {
878  case CLI_INIT:
879  e->command = "dialplan show chanvar";
880  e->usage =
881  "Usage: dialplan show chanvar <channel>\n"
882  " List current channel variables and their values\n";
883  return NULL;
884  case CLI_GENERATE:
885  return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
886  }
887 
888  if (a->argc != e->args + 1) {
889  return CLI_SHOWUSAGE;
890  }
891 
892  chan = ast_channel_get_by_name(a->argv[e->args]);
893  if (!chan) {
894  ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
895  return CLI_FAILURE;
896  }
897 
898  ast_channel_lock(chan);
900  ast_cli(a->fd, "%s=%s\n", ast_var_name(var), ast_var_value(var));
901  }
902  ast_channel_unlock(chan);
903 
904  ast_channel_unref(chan);
905  return CLI_SUCCESS;
906 }
907 
908 static char *handle_set_global(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
909 {
910  switch (cmd) {
911  case CLI_INIT:
912  e->command = "dialplan set global";
913  e->usage =
914  "Usage: dialplan set global <name> <value>\n"
915  " Set global dialplan variable <name> to <value>\n";
916  return NULL;
917  case CLI_GENERATE:
918  return NULL;
919  }
920 
921  if (a->argc != e->args + 2)
922  return CLI_SHOWUSAGE;
923 
924  pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
925  ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
926 
927  return CLI_SUCCESS;
928 }
929 
930 static char *handle_set_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
931 {
932  struct ast_channel *chan;
933  const char *chan_name, *var_name, *var_value;
934 
935  switch (cmd) {
936  case CLI_INIT:
937  e->command = "dialplan set chanvar";
938  e->usage =
939  "Usage: dialplan set chanvar <channel> <varname> <value>\n"
940  " Set channel variable <varname> to <value>\n";
941  return NULL;
942  case CLI_GENERATE:
943  return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
944  }
945 
946  if (a->argc != e->args + 3)
947  return CLI_SHOWUSAGE;
948 
949  chan_name = a->argv[e->args];
950  var_name = a->argv[e->args + 1];
951  var_value = a->argv[e->args + 2];
952 
953  if (!(chan = ast_channel_get_by_name(chan_name))) {
954  ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
955  return CLI_FAILURE;
956  }
957 
958  pbx_builtin_setvar_helper(chan, var_name, var_value);
959 
960  chan = ast_channel_unref(chan);
961 
962  ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name);
963 
964  return CLI_SUCCESS;
965 }
966 
968 {
969  struct ast_var_t *variables;
970  const char *var, *val;
971  int total = 0;
972 
973  if (!chan)
974  return 0;
975 
976  ast_str_reset(*buf);
977 
978  ast_channel_lock(chan);
979 
980  AST_LIST_TRAVERSE(ast_channel_varshead(chan), variables, entries) {
981  if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
982  /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
983  ) {
984  if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
985  ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
986  break;
987  } else
988  total++;
989  } else
990  break;
991  }
992 
993  ast_channel_unlock(chan);
994 
995  return total;
996 }
997 
998 const char *pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
999 {
1000  struct ast_var_t *variables;
1001  const char *ret = NULL;
1002  int i;
1003  struct varshead *places[2] = { NULL, &globals };
1004 
1005  if (!name)
1006  return NULL;
1007 
1008  if (chan) {
1009  ast_channel_lock(chan);
1010  places[0] = ast_channel_varshead(chan);
1011  }
1012 
1013  for (i = 0; i < 2; i++) {
1014  if (!places[i])
1015  continue;
1016  if (places[i] == &globals)
1018  AST_LIST_TRAVERSE(places[i], variables, entries) {
1019  if (!strcmp(name, ast_var_name(variables))) {
1020  ret = ast_var_value(variables);
1021  break;
1022  }
1023  }
1024  if (places[i] == &globals)
1026  if (ret)
1027  break;
1028  }
1029 
1030  if (chan)
1031  ast_channel_unlock(chan);
1032 
1033  return ret;
1034 }
1035 
1036 void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value)
1037 {
1038  struct ast_var_t *newvariable;
1039  struct varshead *headp;
1040 
1041  if (name[strlen(name)-1] == ')') {
1042  char *function = ast_strdupa(name);
1043 
1044  ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
1045  ast_func_write(chan, function, value);
1046  return;
1047  }
1048 
1049  if (chan) {
1050  ast_channel_lock(chan);
1051  headp = ast_channel_varshead(chan);
1052  } else {
1054  headp = &globals;
1055  }
1056 
1057  if (value && (newvariable = ast_var_assign(name, value))) {
1058  if (headp == &globals)
1059  ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
1060  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1061  }
1062 
1063  if (chan)
1064  ast_channel_unlock(chan);
1065  else
1067 }
1068 
1069 int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
1070 {
1071  struct ast_var_t *newvariable;
1072  struct varshead *headp;
1073  const char *nametail = name;
1074  /*! True if the old value was not an empty string. */
1075  int old_value_existed = 0;
1076 
1077  if (name[strlen(name) - 1] == ')') {
1078  char *function = ast_strdupa(name);
1079 
1080  return ast_func_write(chan, function, value);
1081  }
1082 
1083  if (chan) {
1084  ast_channel_lock(chan);
1085  headp = ast_channel_varshead(chan);
1086  } else {
1088  headp = &globals;
1089  }
1090 
1091  /* For comparison purposes, we have to strip leading underscores */
1092  if (*nametail == '_') {
1093  nametail++;
1094  if (*nametail == '_')
1095  nametail++;
1096  }
1097 
1098  AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1099  if (strcmp(ast_var_name(newvariable), nametail) == 0) {
1100  /* there is already such a variable, delete it */
1101  AST_LIST_REMOVE_CURRENT(entries);
1102  old_value_existed = !ast_strlen_zero(ast_var_value(newvariable));
1103  ast_var_delete(newvariable);
1104  break;
1105  }
1106  }
1108 
1109  if (value && (newvariable = ast_var_assign(name, value))) {
1110  if (headp == &globals) {
1111  ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
1112  }
1113  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1114  ast_channel_publish_varset(chan, name, value);
1115  } else if (old_value_existed) {
1116  /* We just deleted a non-empty dialplan variable. */
1117  ast_channel_publish_varset(chan, name, "");
1118  }
1119 
1120  if (chan)
1121  ast_channel_unlock(chan);
1122  else
1124  return 0;
1125 }
1126 
1127 int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
1128 {
1129  char *name, *value, *mydata;
1130 
1131  if (ast_strlen_zero(data)) {
1132  ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
1133  return 0;
1134  }
1135 
1136  mydata = ast_strdupa(data);
1137  name = strsep(&mydata, "=");
1138  value = mydata;
1139  if (!value) {
1140  ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
1141  return 0;
1142  }
1143 
1144  if (strchr(name, ' ')) {
1145  ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
1146  }
1147 
1148  pbx_builtin_setvar_helper(chan, name, value);
1149 
1150  return 0;
1151 }
1152 
1153 int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *vdata)
1154 {
1155  char *data;
1156  int x;
1158  AST_APP_ARG(pair)[24];
1159  );
1161  AST_APP_ARG(name);
1162  AST_APP_ARG(value);
1163  );
1164 
1165  if (ast_strlen_zero(vdata)) {
1166  ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
1167  return 0;
1168  }
1169 
1170  data = ast_strdupa(vdata);
1171  AST_STANDARD_APP_ARGS(args, data);
1172 
1173  for (x = 0; x < args.argc; x++) {
1174  AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
1175  if (pair.argc == 2) {
1176  pbx_builtin_setvar_helper(chan, pair.name, pair.value);
1177  if (strchr(pair.name, ' '))
1178  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);
1179  } else if (!chan) {
1180  ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
1181  } else {
1182  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));
1183  }
1184  }
1185 
1186  return 0;
1187 }
1188 
1190 {
1191  struct ast_var_t *vardata;
1192 
1194  while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
1195  ast_var_delete(vardata);
1197 }
1198 
1199 static struct ast_cli_entry vars_cli[] = {
1200  AST_CLI_DEFINE(handle_show_globals, "Show global dialplan variables"),
1201  AST_CLI_DEFINE(handle_show_chanvar, "Show channel variables"),
1202  AST_CLI_DEFINE(handle_set_global, "Set global dialplan variable"),
1203  AST_CLI_DEFINE(handle_set_chanvar, "Set a channel variable"),
1204 };
1205 
1206 static void unload_pbx_variables(void)
1207 {
1208  ast_cli_unregister_multiple(vars_cli, ARRAY_LEN(vars_cli));
1212 }
1213 
1215 {
1216  int res = 0;
1217 
1218  res |= ast_cli_register_multiple(vars_cli, ARRAY_LEN(vars_cli));
1222 
1223  return res;
1224 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
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.
const char * ast_config_AST_KEY_DIR
Definition: options.c:158
#define ast_rwlock_rdlock(a)
Definition: lock.h:233
#define ast_channel_lock(chan)
Definition: channel.h:2837
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_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define AST_RWLOCK_DEFINE_STATIC(rwlock)
Definition: lock.h:541
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static void unload_pbx_variables(void)
Private include file for pbx.
static char * handle_set_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
const char * ast_config_AST_DB
Definition: options.c:162
Definition: ast_expr2.c:325
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2457
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2873
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...
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:150
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
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
Channel Variables.
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
extract offset:length from variable name.
descriptor for a cli entry.
Definition: cli.h:171
const int argc
Definition: cli.h:160
#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
static struct ast_cli_entry vars_cli[]
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:1796
void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
void pbx_builtin_clear_globals(void)
#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)
Definition: cli.h:152
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
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
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
const char * ast_config_AST_RUN_DIR
Definition: options.c:159
static char * handle_set_global(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct test_val c
const char * str
Definition: app_jack.c:147
struct varshead * ast_channel_varshead(struct ast_channel *chan)
const char * args
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
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:4150
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_rwlock_unlock(a)
Definition: lock.h:232
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
int ast_channel_priority(const struct ast_channel *chan)
#define ast_verb(level,...)
Definition: logger.h:455
const char * line
Definition: cli.h:162
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.
int args
This gets set in ast_cli_register()
Definition: cli.h:185
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Definition: strings.h:738
const char * ast_config_AST_SYSTEM_NAME
Definition: options.c:167
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:444
#define ast_log
Definition: astobj2.c:42
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_AGI_DIR
Definition: options.c:157
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1266
struct ast_var_t::@243 entries
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 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
A set of macros to manage forward-linked lists.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
const char * ast_channel_exten(const struct ast_channel *chan)
Core PBX routines and definitions.
static char * handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI support for listing chanvar&#39;s variables in a parseable way.
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char *const * argv
Definition: cli.h:161
const char * ast_config_AST_DATA_DIR
Definition: options.c:155
#define LOG_ERROR
Definition: logger.h:285
int load_pbx_variables(void)
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define CLI_SHOWUSAGE
Definition: cli.h:45
const char * ast_config_AST_CONFIG_DIR
Definition: options.c:148
void ast_channel_publish_varset(struct ast_channel *chan, const char *variable, const char *value)
Publish a ast_channel_varset for a channel.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
void ast_var_delete(struct ast_var_t *var)
Definition: extconf.c:2473
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
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:156
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_strlen_zero(a)
Definition: muted.c:73
#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:2838
#define CLI_FAILURE
Definition: cli.h:46
#define VAR_BUF_SIZE
Definition: pbx_private.h:68
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
#define ast_var_assign(name, value)
Definition: chanvars.h:40
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...
const char * word
Definition: cli.h:163
Prototypes for public functions only of internal interest,.
const char * ast_config_AST_SPOOL_DIR
Definition: options.c:151
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:251
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
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_rwlock_wrlock(a)
Definition: lock.h:234
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:93
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
#define CLI_SUCCESS
Definition: cli.h:44
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
char * strsep(char **str, const char *delims)
Standard Command Line Interface.
int ast_channel_hangupcause(const struct ast_channel *chan)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
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
static ast_rwlock_t globalslock
const char * ast_channel_name(const struct ast_channel *chan)
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:1783
static int total
Definition: res_adsi.c:968
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
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
const char * name
Definition: test_config.c:85
void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
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
const char * ast_channel_context(const struct ast_channel *chan)
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
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.
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1439
Asterisk module definitions.
const char * ast_config_AST_VAR_DIR
Definition: options.c:154
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
executes a write operation on a function
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan)
Evaluate the given expression.
Definition: ast_expr2f.c:2405
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.
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...
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
#define AST_APP_ARG(name)
Define an application argument.
static struct test_val a