Asterisk - The Open Source Telephony Project  GIT-master-44aef04
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, "ASTCACHEDIR")) {
332  } else if (!strcmp(var, "ASTETCDIR")) {
334  } else if (!strcmp(var, "ASTMODDIR")) {
336  } else if (!strcmp(var, "ASTVARLIBDIR")) {
338  } else if (!strcmp(var, "ASTDBDIR")) {
339  s = ast_config_AST_DB;
340  } else if (!strcmp(var, "ASTKEYDIR")) {
342  } else if (!strcmp(var, "ASTDATADIR")) {
344  } else if (!strcmp(var, "ASTAGIDIR")) {
346  } else if (!strcmp(var, "ASTSPOOLDIR")) {
348  } else if (!strcmp(var, "ASTRUNDIR")) {
350  } else if (!strcmp(var, "ASTLOGDIR")) {
352  } else if (!strcmp(var, "ENTITYID")) {
353  ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
354  s = workspace;
355  }
356  }
357  /* if not found, look into chanvars or global vars */
358  for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
359  struct ast_var_t *variables;
360  if (!places[i])
361  continue;
362  if (places[i] == &globals)
364  AST_LIST_TRAVERSE(places[i], variables, entries) {
365  if (!strcmp(ast_var_name(variables), var)) {
366  s = ast_var_value(variables);
367  break;
368  }
369  }
370  if (places[i] == &globals)
372  }
373  if (s == &not_found || s == NULL) {
374  ast_debug(5, "Result of '%s' is NULL\n", var);
375  ret = NULL;
376  } else {
377  ast_debug(5, "Result of '%s' is '%s'\n", var, s);
378  if (s != ast_str_buffer(*str)) {
379  ast_str_set(str, maxlen, "%s", s);
380  }
381  ret = ast_str_buffer(*str);
382  if (need_substring) {
383  ret = ast_str_substring(*str, offset, length);
384  ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
385  }
386  }
387 
388  if (c) {
390  }
391  return ret;
392 }
393 
394 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)
395 {
396  /* Substitutes variables into buf, based on string templ */
397  const char *whereweare;
398  struct ast_str *substr1 = ast_str_create(16);
399  struct ast_str *substr2 = NULL;
400  struct ast_str *substr3 = ast_str_create(16);
401 
402  ast_str_reset(*buf);
403 
404  if (!substr1 || !substr3) {
405  if (used) {
406  *used = ast_str_strlen(*buf);
407  }
408  ast_free(substr1);
409  ast_free(substr3);
410  return;
411  }
412 
413  whereweare = templ;
414  while (!ast_strlen_zero(whereweare)) {
415  const char *nextvar = NULL;
416  const char *nextexp = NULL;
417  const char *nextthing;
418  const char *vars;
419  const char *vare;
420  char *finalvars;
421  int pos;
422  int brackets;
423  int needsub;
424  int len;
425 
426  /* reset our buffer */
427  ast_str_reset(substr3);
428 
429  /* Determine how much simply needs to be copied to the output buf. */
430  nextthing = strchr(whereweare, '$');
431  if (nextthing) {
432  pos = nextthing - whereweare;
433  switch (nextthing[1]) {
434  case '{':
435  /* Variable substitution */
436  nextvar = nextthing;
437  break;
438  case '[':
439  /* Expression substitution */
440  nextexp = nextthing;
441  break;
442  default:
443  /* '$' is not part of a substitution so include it too. */
444  ++pos;
445  break;
446  }
447  } else {
448  /* We're copying the whole remaining string */
449  pos = strlen(whereweare);
450  }
451 
452  if (pos) {
453  /* Copy that many bytes */
454  ast_str_append_substr(buf, maxlen, whereweare, pos);
455 
456  whereweare += pos;
457  }
458 
459  if (nextvar) {
460  int offset;
461  int offset2;
462  int isfunction;
463  int res;
464 
465  /* We have a variable. Find the start and end, and determine
466  if we are going to have to recursively call ourselves on the
467  contents */
468  vars = vare = nextvar + 2;
469  brackets = 1;
470  needsub = 0;
471 
472  /* Find the end of it */
473  while (brackets && *vare) {
474  if ((vare[0] == '$') && (vare[1] == '{')) {
475  needsub++;
476  brackets++;
477  vare++;
478  } else if (vare[0] == '{') {
479  brackets++;
480  } else if (vare[0] == '}') {
481  brackets--;
482  } else if ((vare[0] == '$') && (vare[1] == '[')) {
483  needsub++;
484  vare++;
485  }
486  vare++;
487  }
488  len = vare - vars;
489  if (brackets) {
490  ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
491  } else {
492  /* Don't count the closing '}' in the length. */
493  --len;
494  }
495 
496  /* Skip totally over variable string */
497  whereweare = vare;
498 
499  /* Store variable name expression to lookup. */
500  ast_str_set_substr(&substr1, 0, vars, len);
501  ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
502 
503  /* Substitute if necessary */
504  if (needsub) {
505  if (!substr2) {
506  substr2 = ast_str_create(16);
507  if (!substr2) {
508  continue;
509  }
510  }
511  ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), NULL);
512  finalvars = ast_str_buffer(substr2);
513  } else {
514  finalvars = ast_str_buffer(substr1);
515  }
516 
517  parse_variable_name(finalvars, &offset, &offset2, &isfunction);
518  if (isfunction) {
519  /* Evaluate function */
520  if (c || !headp) {
521  res = ast_func_read2(c, finalvars, &substr3, 0);
522  } else {
523  struct varshead old;
524  struct ast_channel *bogus;
525 
526  bogus = ast_dummy_channel_alloc();
527  if (bogus) {
528  old = *ast_channel_varshead(bogus);
529  *ast_channel_varshead(bogus) = *headp;
530  res = ast_func_read2(bogus, finalvars, &substr3, 0);
531  /* Don't deallocate the varshead that was passed in */
532  *ast_channel_varshead(bogus) = old;
533  ast_channel_unref(bogus);
534  } else {
535  ast_log(LOG_ERROR, "Unable to allocate bogus channel for function value substitution.\n");
536  res = -1;
537  }
538  }
539  ast_debug(2, "Function %s result is '%s'\n",
540  finalvars, res ? "" : ast_str_buffer(substr3));
541  } else {
542  /* Retrieve variable value */
543  ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
544  res = 0;
545  }
546  if (!res) {
547  ast_str_substring(substr3, offset, offset2);
548  ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
549  }
550  } else if (nextexp) {
551  /* We have an expression. Find the start and end, and determine
552  if we are going to have to recursively call ourselves on the
553  contents */
554  vars = vare = nextexp + 2;
555  brackets = 1;
556  needsub = 0;
557 
558  /* Find the end of it */
559  while (brackets && *vare) {
560  if ((vare[0] == '$') && (vare[1] == '[')) {
561  needsub++;
562  brackets++;
563  vare++;
564  } else if (vare[0] == '[') {
565  brackets++;
566  } else if (vare[0] == ']') {
567  brackets--;
568  } else if ((vare[0] == '$') && (vare[1] == '{')) {
569  needsub++;
570  vare++;
571  }
572  vare++;
573  }
574  len = vare - vars;
575  if (brackets) {
576  ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
577  } else {
578  /* Don't count the closing ']' in the length. */
579  --len;
580  }
581 
582  /* Skip totally over expression */
583  whereweare = vare;
584 
585  /* Store expression to evaluate. */
586  ast_str_set_substr(&substr1, 0, vars, len);
587 
588  /* Substitute if necessary */
589  if (needsub) {
590  if (!substr2) {
591  substr2 = ast_str_create(16);
592  if (!substr2) {
593  continue;
594  }
595  }
596  ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), NULL);
597  finalvars = ast_str_buffer(substr2);
598  } else {
599  finalvars = ast_str_buffer(substr1);
600  }
601 
602  if (ast_str_expr(&substr3, 0, c, finalvars)) {
603  ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
604  }
605  ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
606  }
607  }
608  if (used) {
609  *used = ast_str_strlen(*buf);
610  }
611  ast_free(substr1);
612  ast_free(substr2);
613  ast_free(substr3);
614 }
615 
616 void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
617 {
618  ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, NULL);
619 }
620 
621 void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
622 {
623  ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, NULL);
624 }
625 
626 void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
627 {
628  /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */
629  const char *whereweare;
630  const char *orig_cp2 = cp2;
631  char ltmp[VAR_BUF_SIZE];
632  char var[VAR_BUF_SIZE];
633 
634  *cp2 = 0; /* just in case nothing ends up there */
635  whereweare = cp1;
636  while (!ast_strlen_zero(whereweare) && count) {
637  char *nextvar = NULL;
638  char *nextexp = NULL;
639  char *nextthing;
640  char *vars;
641  char *vare;
642  int length;
643  int pos;
644  int brackets;
645  int needsub;
646  int len;
647 
648  /* Determine how much simply needs to be copied to the output buf. */
649  nextthing = strchr(whereweare, '$');
650  if (nextthing) {
651  pos = nextthing - whereweare;
652  switch (nextthing[1]) {
653  case '{':
654  /* Variable substitution */
655  nextvar = nextthing;
656  break;
657  case '[':
658  /* Expression substitution */
659  nextexp = nextthing;
660  break;
661  default:
662  /* '$' is not part of a substitution so include it too. */
663  ++pos;
664  break;
665  }
666  } else {
667  /* We're copying the whole remaining string */
668  pos = strlen(whereweare);
669  }
670 
671  if (pos) {
672  /* Can't copy more than 'count' bytes */
673  if (pos > count)
674  pos = count;
675 
676  /* Copy that many bytes */
677  memcpy(cp2, whereweare, pos);
678 
679  count -= pos;
680  cp2 += pos;
681  whereweare += pos;
682  *cp2 = 0;
683  }
684 
685  if (nextvar) {
686  int offset;
687  int offset2;
688  int isfunction;
689  char *cp4;
690  char workspace[VAR_BUF_SIZE] = "";
691 
692  /* We have a variable. Find the start and end, and determine
693  if we are going to have to recursively call ourselves on the
694  contents */
695  vars = vare = nextvar + 2;
696  brackets = 1;
697  needsub = 0;
698 
699  /* Find the end of it */
700  while (brackets && *vare) {
701  if ((vare[0] == '$') && (vare[1] == '{')) {
702  needsub++;
703  brackets++;
704  vare++;
705  } else if (vare[0] == '{') {
706  brackets++;
707  } else if (vare[0] == '}') {
708  brackets--;
709  } else if ((vare[0] == '$') && (vare[1] == '[')) {
710  needsub++;
711  vare++;
712  }
713  vare++;
714  }
715  len = vare - vars;
716  if (brackets) {
717  ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
718  } else {
719  /* Don't count the closing '}' in the length. */
720  --len;
721  }
722 
723  /* Skip totally over variable string */
724  whereweare = vare;
725 
726  /* Store variable name expression to lookup (and truncate). */
727  ast_copy_string(var, vars, len + 1);
728 
729  /* Substitute if necessary */
730  if (needsub) {
731  pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, NULL);
732  vars = ltmp;
733  } else {
734  vars = var;
735  }
736 
737  parse_variable_name(vars, &offset, &offset2, &isfunction);
738  if (isfunction) {
739  /* Evaluate function */
740  if (c || !headp)
741  cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
742  else {
743  struct varshead old;
744  struct ast_channel *bogus;
745 
746  bogus = ast_dummy_channel_alloc();
747  if (bogus) {
748  old = *ast_channel_varshead(bogus);
749  *ast_channel_varshead(bogus) = *headp;
750  cp4 = ast_func_read(bogus, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
751  /* Don't deallocate the varshead that was passed in */
752  *ast_channel_varshead(bogus) = old;
753  ast_channel_unref(bogus);
754  } else {
755  ast_log(LOG_ERROR, "Unable to allocate bogus channel for function value substitution.\n");
756  cp4 = NULL;
757  }
758  }
759  ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
760  } else {
761  /* Retrieve variable value */
762  pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
763  }
764  if (cp4) {
765  cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
766 
767  length = strlen(cp4);
768  if (length > count)
769  length = count;
770  memcpy(cp2, cp4, length);
771  count -= length;
772  cp2 += length;
773  *cp2 = 0;
774  }
775  } else if (nextexp) {
776  /* We have an expression. Find the start and end, and determine
777  if we are going to have to recursively call ourselves on the
778  contents */
779  vars = vare = nextexp + 2;
780  brackets = 1;
781  needsub = 0;
782 
783  /* Find the end of it */
784  while (brackets && *vare) {
785  if ((vare[0] == '$') && (vare[1] == '[')) {
786  needsub++;
787  brackets++;
788  vare++;
789  } else if (vare[0] == '[') {
790  brackets++;
791  } else if (vare[0] == ']') {
792  brackets--;
793  } else if ((vare[0] == '$') && (vare[1] == '{')) {
794  needsub++;
795  vare++;
796  }
797  vare++;
798  }
799  len = vare - vars;
800  if (brackets) {
801  ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
802  } else {
803  /* Don't count the closing ']' in the length. */
804  --len;
805  }
806 
807  /* Skip totally over expression */
808  whereweare = vare;
809 
810  /* Store expression to evaluate (and truncate). */
811  ast_copy_string(var, vars, len + 1);
812 
813  /* Substitute if necessary */
814  if (needsub) {
815  pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, NULL);
816  vars = ltmp;
817  } else {
818  vars = var;
819  }
820 
821  length = ast_expr(vars, cp2, count, c);
822  if (length) {
823  ast_debug(1, "Expression result is '%s'\n", cp2);
824  count -= length;
825  cp2 += length;
826  *cp2 = 0;
827  }
828  }
829  }
830  if (used) {
831  *used = cp2 - orig_cp2;
832  }
833 }
834 
835 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
836 {
837  pbx_substitute_variables_helper_full(c, (c) ? ast_channel_varshead(c) : NULL, cp1, cp2, count, NULL);
838 }
839 
840 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
841 {
842  pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, NULL);
843 }
844 
845 /*! \brief CLI support for listing global variables in a parseable way */
846 static char *handle_show_globals(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
847 {
848  int i = 0;
849  struct ast_var_t *newvariable;
850 
851  switch (cmd) {
852  case CLI_INIT:
853  e->command = "dialplan show globals";
854  e->usage =
855  "Usage: dialplan show globals\n"
856  " List current global dialplan variables and their values\n";
857  return NULL;
858  case CLI_GENERATE:
859  return NULL;
860  }
861 
863  AST_LIST_TRAVERSE (&globals, newvariable, entries) {
864  i++;
865  ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
866  }
868  ast_cli(a->fd, "\n -- %d variable(s)\n", i);
869 
870  return CLI_SUCCESS;
871 }
872 
873 /*! \brief CLI support for listing chanvar's variables in a parseable way */
874 static char *handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
875 {
876  struct ast_channel *chan;
877  struct ast_var_t *var;
878 
879  switch (cmd) {
880  case CLI_INIT:
881  e->command = "dialplan show chanvar";
882  e->usage =
883  "Usage: dialplan show chanvar <channel>\n"
884  " List current channel variables and their values\n";
885  return NULL;
886  case CLI_GENERATE:
887  return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
888  }
889 
890  if (a->argc != e->args + 1) {
891  return CLI_SHOWUSAGE;
892  }
893 
894  chan = ast_channel_get_by_name(a->argv[e->args]);
895  if (!chan) {
896  ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
897  return CLI_FAILURE;
898  }
899 
900  ast_channel_lock(chan);
902  ast_cli(a->fd, "%s=%s\n", ast_var_name(var), ast_var_value(var));
903  }
904  ast_channel_unlock(chan);
905 
906  ast_channel_unref(chan);
907  return CLI_SUCCESS;
908 }
909 
910 static char *handle_set_global(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
911 {
912  switch (cmd) {
913  case CLI_INIT:
914  e->command = "dialplan set global";
915  e->usage =
916  "Usage: dialplan set global <name> <value>\n"
917  " Set global dialplan variable <name> to <value>\n";
918  return NULL;
919  case CLI_GENERATE:
920  return NULL;
921  }
922 
923  if (a->argc != e->args + 2)
924  return CLI_SHOWUSAGE;
925 
926  pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
927  ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
928 
929  return CLI_SUCCESS;
930 }
931 
932 static char *handle_set_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
933 {
934  struct ast_channel *chan;
935  const char *chan_name, *var_name, *var_value;
936 
937  switch (cmd) {
938  case CLI_INIT:
939  e->command = "dialplan set chanvar";
940  e->usage =
941  "Usage: dialplan set chanvar <channel> <varname> <value>\n"
942  " Set channel variable <varname> to <value>\n";
943  return NULL;
944  case CLI_GENERATE:
945  return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
946  }
947 
948  if (a->argc != e->args + 3)
949  return CLI_SHOWUSAGE;
950 
951  chan_name = a->argv[e->args];
952  var_name = a->argv[e->args + 1];
953  var_value = a->argv[e->args + 2];
954 
955  if (!(chan = ast_channel_get_by_name(chan_name))) {
956  ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
957  return CLI_FAILURE;
958  }
959 
960  pbx_builtin_setvar_helper(chan, var_name, var_value);
961 
962  chan = ast_channel_unref(chan);
963 
964  ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name);
965 
966  return CLI_SUCCESS;
967 }
968 
970 {
971  struct ast_var_t *variables;
972  const char *var, *val;
973  int total = 0;
974 
975  if (!chan)
976  return 0;
977 
978  ast_str_reset(*buf);
979 
980  ast_channel_lock(chan);
981 
982  AST_LIST_TRAVERSE(ast_channel_varshead(chan), variables, entries) {
983  if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
984  /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
985  ) {
986  if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
987  ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
988  break;
989  } else
990  total++;
991  } else
992  break;
993  }
994 
995  ast_channel_unlock(chan);
996 
997  return total;
998 }
999 
1000 const char *pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
1001 {
1002  struct ast_var_t *variables;
1003  const char *ret = NULL;
1004  int i;
1005  struct varshead *places[2] = { NULL, &globals };
1006 
1007  if (!name)
1008  return NULL;
1009 
1010  if (chan) {
1011  ast_channel_lock(chan);
1012  places[0] = ast_channel_varshead(chan);
1013  }
1014 
1015  for (i = 0; i < 2; i++) {
1016  if (!places[i])
1017  continue;
1018  if (places[i] == &globals)
1020  AST_LIST_TRAVERSE(places[i], variables, entries) {
1021  if (!strcmp(name, ast_var_name(variables))) {
1022  ret = ast_var_value(variables);
1023  break;
1024  }
1025  }
1026  if (places[i] == &globals)
1028  if (ret)
1029  break;
1030  }
1031 
1032  if (chan)
1033  ast_channel_unlock(chan);
1034 
1035  return ret;
1036 }
1037 
1038 void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value)
1039 {
1040  struct ast_var_t *newvariable;
1041  struct varshead *headp;
1042 
1043  if (name[strlen(name)-1] == ')') {
1044  char *function = ast_strdupa(name);
1045 
1046  ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
1047  ast_func_write(chan, function, value);
1048  return;
1049  }
1050 
1051  if (chan) {
1052  ast_channel_lock(chan);
1053  headp = ast_channel_varshead(chan);
1054  } else {
1056  headp = &globals;
1057  }
1058 
1059  if (value && (newvariable = ast_var_assign(name, value))) {
1060  if (headp == &globals)
1061  ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
1062  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1063  }
1064 
1065  if (chan)
1066  ast_channel_unlock(chan);
1067  else
1069 }
1070 
1071 int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
1072 {
1073  struct ast_var_t *newvariable;
1074  struct varshead *headp;
1075  const char *nametail = name;
1076  /*! True if the old value was not an empty string. */
1077  int old_value_existed = 0;
1078 
1079  if (name[strlen(name) - 1] == ')') {
1080  char *function = ast_strdupa(name);
1081 
1082  return ast_func_write(chan, function, value);
1083  }
1084 
1085  if (chan) {
1086  ast_channel_lock(chan);
1087  headp = ast_channel_varshead(chan);
1088  } else {
1090  headp = &globals;
1091  }
1092 
1093  /* For comparison purposes, we have to strip leading underscores */
1094  if (*nametail == '_') {
1095  nametail++;
1096  if (*nametail == '_')
1097  nametail++;
1098  }
1099 
1100  AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
1101  if (strcmp(ast_var_name(newvariable), nametail) == 0) {
1102  /* there is already such a variable, delete it */
1103  AST_LIST_REMOVE_CURRENT(entries);
1104  old_value_existed = !ast_strlen_zero(ast_var_value(newvariable));
1105  ast_var_delete(newvariable);
1106  break;
1107  }
1108  }
1110 
1111  if (value && (newvariable = ast_var_assign(name, value))) {
1112  if (headp == &globals) {
1113  ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
1114  }
1115  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
1116  ast_channel_publish_varset(chan, name, value);
1117  } else if (old_value_existed) {
1118  /* We just deleted a non-empty dialplan variable. */
1119  ast_channel_publish_varset(chan, name, "");
1120  }
1121 
1122  if (chan)
1123  ast_channel_unlock(chan);
1124  else
1126  return 0;
1127 }
1128 
1129 int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
1130 {
1131  char *name, *value, *mydata;
1132 
1133  if (ast_strlen_zero(data)) {
1134  ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
1135  return 0;
1136  }
1137 
1138  mydata = ast_strdupa(data);
1139  name = strsep(&mydata, "=");
1140  value = mydata;
1141  if (!value) {
1142  ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
1143  return 0;
1144  }
1145 
1146  if (strchr(name, ' ')) {
1147  ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
1148  }
1149 
1150  pbx_builtin_setvar_helper(chan, name, value);
1151 
1152  return 0;
1153 }
1154 
1155 int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *vdata)
1156 {
1157  char *data;
1158  int x;
1160  AST_APP_ARG(pair)[24];
1161  );
1163  AST_APP_ARG(name);
1164  AST_APP_ARG(value);
1165  );
1166 
1167  if (ast_strlen_zero(vdata)) {
1168  ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
1169  return 0;
1170  }
1171 
1172  data = ast_strdupa(vdata);
1173  AST_STANDARD_APP_ARGS(args, data);
1174 
1175  for (x = 0; x < args.argc; x++) {
1176  AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
1177  if (pair.argc == 2) {
1178  pbx_builtin_setvar_helper(chan, pair.name, pair.value);
1179  if (strchr(pair.name, ' '))
1180  ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", pair.name, pair.value);
1181  } else if (!chan) {
1182  ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
1183  } else {
1184  ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, ast_channel_exten(chan), ast_channel_context(chan), ast_channel_priority(chan));
1185  }
1186  }
1187 
1188  return 0;
1189 }
1190 
1192 {
1193  struct ast_var_t *vardata;
1194 
1196  while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
1197  ast_var_delete(vardata);
1199 }
1200 
1201 static struct ast_cli_entry vars_cli[] = {
1202  AST_CLI_DEFINE(handle_show_globals, "Show global dialplan variables"),
1203  AST_CLI_DEFINE(handle_show_chanvar, "Show channel variables"),
1204  AST_CLI_DEFINE(handle_set_global, "Set global dialplan variable"),
1205  AST_CLI_DEFINE(handle_set_chanvar, "Set a channel variable"),
1206 };
1207 
1208 static void unload_pbx_variables(void)
1209 {
1210  ast_cli_unregister_multiple(vars_cli, ARRAY_LEN(vars_cli));
1214 }
1215 
1217 {
1218  int res = 0;
1219 
1220  res |= ast_cli_register_multiple(vars_cli, ARRAY_LEN(vars_cli));
1224 
1225  return res;
1226 }
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:161
#define ast_rwlock_rdlock(a)
Definition: lock.h:233
#define ast_channel_lock(chan)
Definition: channel.h:2902
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
const char * ast_config_AST_CACHE_DIR
Definition: options.c:150
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:165
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:2458
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2938
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:153
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:1807
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:162
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:4159
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:170
Number structure.
Definition: app_followme.c:154
static const char * ast_str_substring(struct ast_str *value, int offset, int length)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h: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:160
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:1283
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:158
#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:151
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:159
#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:2903
#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:154
#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:1830
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:1450
Asterisk module definitions.
const char * ast_config_AST_VAR_DIR
Definition: options.c:157
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