Asterisk - The Open Source Telephony Project  18.5.0
pbx_functions.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2015, CFWare, LLC
5  *
6  * Corey Farrell <[email protected]>
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 Custom function management routines.
22  *
23  * \author Corey Farrell <[email protected]>
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/cli.h"
34 #include "asterisk/linkedlists.h"
35 #include "asterisk/module.h"
36 #include "asterisk/pbx.h"
37 #include "asterisk/term.h"
38 #include "asterisk/threadstorage.h"
39 #include "asterisk/xmldoc.h"
40 #include "pbx_private.h"
41 
42 /*!
43  * \brief A thread local indicating whether the current thread can run
44  * 'dangerous' dialplan functions.
45  */
47 
48 /*!
49  * \brief Set to true (non-zero) to globally allow all dangerous dialplan
50  * functions to run.
51  */
52 static int live_dangerously;
53 
54 /*!
55  * \brief Registered functions container.
56  *
57  * It is sorted by function name.
58  */
60 
61 static char *handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
62 {
63  struct ast_custom_function *acf;
64  int count_acf = 0;
65  int like = 0;
66 
67  switch (cmd) {
68  case CLI_INIT:
69  e->command = "core show functions [like]";
70  e->usage =
71  "Usage: core show functions [like <text>]\n"
72  " List builtin functions, optionally only those matching a given string\n";
73  return NULL;
74  case CLI_GENERATE:
75  return NULL;
76  }
77 
78  if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
79  like = 1;
80  } else if (a->argc != 3) {
81  return CLI_SHOWUSAGE;
82  }
83 
84  ast_cli(a->fd, "%s Custom Functions:\n"
85  "--------------------------------------------------------------------------------\n",
86  like ? "Matching" : "Installed");
87 
89  AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
90  if (!like || strstr(acf->name, a->argv[4])) {
91  count_acf++;
92  ast_cli(a->fd, "%-20.20s %-35.35s %s\n",
93  S_OR(acf->name, ""),
94  S_OR(acf->syntax, ""),
95  S_OR(acf->synopsis, ""));
96  }
97  }
99 
100  ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
101 
102  return CLI_SUCCESS;
103 }
104 
105 static char *complete_functions(const char *word, int pos, int state)
106 {
107  struct ast_custom_function *cur;
108  char *ret = NULL;
109  int which = 0;
110  int wordlen;
111  int cmp;
112 
113  if (pos != 3) {
114  return NULL;
115  }
116 
117  wordlen = strlen(word);
119  AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
120  /*
121  * Do a case-insensitive search for convenience in this
122  * 'complete' function.
123  *
124  * We must search the entire container because the functions are
125  * sorted and normally found case sensitively.
126  */
127  cmp = strncasecmp(word, cur->name, wordlen);
128  if (!cmp) {
129  /* Found match. */
130  if (++which <= state) {
131  /* Not enough matches. */
132  continue;
133  }
134  ret = ast_strdup(cur->name);
135  break;
136  }
137  }
139 
140  return ret;
141 }
142 
143 static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
144 {
145  struct ast_custom_function *acf;
146  /* Maximum number of characters added by terminal coloring is 22 */
147  char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
148  char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
149  char stxtitle[40], *syntax = NULL, *arguments = NULL;
150  int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
151 
152  switch (cmd) {
153  case CLI_INIT:
154  e->command = "core show function";
155  e->usage =
156  "Usage: core show function <function>\n"
157  " Describe a particular dialplan function.\n";
158  return NULL;
159  case CLI_GENERATE:
160  return complete_functions(a->word, a->pos, a->n);
161  }
162 
163  if (a->argc != 4) {
164  return CLI_SHOWUSAGE;
165  }
166 
167  if (!(acf = ast_custom_function_find(a->argv[3]))) {
168  ast_cli(a->fd, "No function by that name registered.\n");
169 
170  return CLI_FAILURE;
171  }
172 
173  syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
174  syntax = ast_malloc(syntax_size);
175  if (!syntax) {
176  ast_cli(a->fd, "Memory allocation failure!\n");
177 
178  return CLI_FAILURE;
179  }
180 
181  snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name);
182  term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
183  term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
184  term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
185  term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
186  term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
187  term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
188  term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
189 #ifdef AST_XML_DOCS
190  if (acf->docsrc == AST_XML_DOC) {
191  arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
192  synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
193  description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
194  seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
195  } else
196 #endif
197  {
198  synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
199  synopsis = ast_malloc(synopsis_size);
200 
201  description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
202  description = ast_malloc(description_size);
203 
204  arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
205  arguments = ast_malloc(arguments_size);
206 
207  seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
208  seealso = ast_malloc(seealso_size);
209 
210  /* check allocated memory. */
211  if (!synopsis || !description || !arguments || !seealso) {
212  ast_free(synopsis);
213  ast_free(description);
214  ast_free(arguments);
215  ast_free(seealso);
216  ast_free(syntax);
217 
218  return CLI_FAILURE;
219  }
220 
221  term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
222  term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
223  term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
224  term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
225  }
226 
227  ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
228  infotitle, syntitle, synopsis, destitle, description,
229  stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
230 
231  ast_free(arguments);
232  ast_free(synopsis);
233  ast_free(description);
234  ast_free(seealso);
235  ast_free(syntax);
236 
237  return CLI_SUCCESS;
238 }
239 
241 {
242  struct ast_custom_function *cur;
243  int cmp;
244 
245  AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
246  cmp = strcmp(name, cur->name);
247  if (cmp > 0) {
248  continue;
249  }
250  if (!cmp) {
251  /* Found it. */
252  break;
253  }
254  /* Not in container. */
255  cur = NULL;
256  break;
257  }
258 
259  return cur;
260 }
261 
263 {
264  struct ast_custom_function *acf;
265 
269 
270  return acf;
271 }
272 
274 {
275  struct ast_custom_function *cur;
276 
277  if (!acf) {
278  return -1;
279  }
280 
282  cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist);
283  if (cur) {
284 #ifdef AST_XML_DOCS
285  if (cur->docsrc == AST_XML_DOC) {
287  }
288 #endif
289  ast_verb(2, "Unregistered custom function %s\n", cur->name);
290  }
292 
293  return cur ? 0 : -1;
294 }
295 
296 /*!
297  * \brief Returns true if given custom function escalates privileges on read.
298  *
299  * \param acf Custom function to query.
300  * \return True (non-zero) if reads escalate privileges.
301  * \return False (zero) if reads just read.
302  */
303 static int read_escalates(const struct ast_custom_function *acf)
304 {
305  return acf->read_escalates;
306 }
307 
308 /*!
309  * \brief Returns true if given custom function escalates privileges on write.
310  *
311  * \param acf Custom function to query.
312  * \return True (non-zero) if writes escalate privileges.
313  * \return False (zero) if writes just write.
314  */
315 static int write_escalates(const struct ast_custom_function *acf)
316 {
317  return acf->write_escalates;
318 }
319 
320 /*! \internal
321  * \brief Retrieve the XML documentation of a specified ast_custom_function,
322  * and populate ast_custom_function string fields.
323  * \param acf ast_custom_function structure with empty 'desc' and 'synopsis'
324  * but with a function 'name'.
325  * \retval -1 On error.
326  * \retval 0 On succes.
327  */
328 static int acf_retrieve_docs(struct ast_custom_function *acf)
329 {
330 #ifdef AST_XML_DOCS
331  char *tmpxml;
332 
333  /* Let's try to find it in the Documentation XML */
334  if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
335  return 0;
336  }
337 
338  if (ast_string_field_init(acf, 128)) {
339  return -1;
340  }
341 
342  /* load synopsis */
343  tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
344  ast_string_field_set(acf, synopsis, tmpxml);
345  ast_free(tmpxml);
346 
347  /* load description */
348  tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
349  ast_string_field_set(acf, desc, tmpxml);
350  ast_free(tmpxml);
351 
352  /* load syntax */
353  tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
354  ast_string_field_set(acf, syntax, tmpxml);
355  ast_free(tmpxml);
356 
357  /* load arguments */
358  tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
359  ast_string_field_set(acf, arguments, tmpxml);
360  ast_free(tmpxml);
361 
362  /* load seealso */
363  tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
364  ast_string_field_set(acf, seealso, tmpxml);
365  ast_free(tmpxml);
366 
367  acf->docsrc = AST_XML_DOC;
368 #endif
369 
370  return 0;
371 }
372 
374 {
375  struct ast_custom_function *cur;
376 
377  if (!acf) {
378  return -1;
379  }
380 
381  acf->mod = mod;
382 #ifdef AST_XML_DOCS
383  acf->docsrc = AST_STATIC_DOC;
384 #endif
385 
386  if (acf_retrieve_docs(acf)) {
387  return -1;
388  }
389 
391 
393  if (cur) {
394  ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
396  return -1;
397  }
398 
399  /* Store in alphabetical order */
400  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
401  if (strcmp(acf->name, cur->name) < 0) {
402  AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
403  break;
404  }
405  }
407  if (!cur) {
408  AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
409  }
410 
412 
413  ast_verb(2, "Registered custom function '" COLORIZE_FMT "'\n", COLORIZE(COLOR_BRCYAN, 0, acf->name));
414 
415  return 0;
416 }
417 
419 {
420  int res;
421 
422  res = __ast_custom_function_register(acf, mod);
423  if (res != 0) {
424  return -1;
425  }
426 
427  switch (escalation) {
428  case AST_CFE_NONE:
429  break;
430  case AST_CFE_READ:
431  acf->read_escalates = 1;
432  break;
433  case AST_CFE_WRITE:
434  acf->write_escalates = 1;
435  break;
436  case AST_CFE_BOTH:
437  acf->read_escalates = 1;
438  acf->write_escalates = 1;
439  break;
440  }
441 
442  return 0;
443 }
444 
445 /*! \brief return a pointer to the arguments of the function,
446  * and terminates the function name with '\\0'
447  */
448 static char *func_args(char *function)
449 {
450  char *args = strchr(function, '(');
451 
452  if (!args) {
453  ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function);
454  } else {
455  char *p;
456  *args++ = '\0';
457  if ((p = strrchr(args, ')'))) {
458  *p = '\0';
459  } else {
460  ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
461  }
462  }
463  return args;
464 }
465 
466 void pbx_live_dangerously(int new_live_dangerously)
467 {
468  if (new_live_dangerously && !live_dangerously) {
469  ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n"
470  "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n");
471  }
472 
473  if (!new_live_dangerously && live_dangerously) {
474  ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n");
475  }
476  live_dangerously = new_live_dangerously;
477 }
478 
480 {
481  int *thread_inhibit_escalations;
482 
483  thread_inhibit_escalations = ast_threadstorage_get(
484  &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
485  if (thread_inhibit_escalations == NULL) {
486  ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n");
487  return -1;
488  }
489 
490  *thread_inhibit_escalations = 1;
491  return 0;
492 }
493 
495 {
496  int *thread_inhibit_escalations;
497  int orig;
498 
499  thread_inhibit_escalations = ast_threadstorage_get(
500  &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
501  if (thread_inhibit_escalations == NULL) {
502  ast_log(LOG_ERROR, "Error swapping privilege escalations inhibit for current thread\n");
503  return -1;
504  }
505 
506  orig = *thread_inhibit_escalations;
507  *thread_inhibit_escalations = !!inhibit;
508  return orig;
509 }
510 
511 /*!
512  * \brief Indicates whether the current thread inhibits the execution of
513  * dangerous functions.
514  *
515  * \return True (non-zero) if dangerous function execution is inhibited.
516  * \return False (zero) if dangerous function execution is allowed.
517  */
519 {
520  int *thread_inhibit_escalations;
521 
522  thread_inhibit_escalations = ast_threadstorage_get(
523  &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
524  if (thread_inhibit_escalations == NULL) {
525  ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n");
526  /* On error, assume that we are inhibiting */
527  return 1;
528  }
529 
530  return *thread_inhibit_escalations;
531 }
532 
533 /*!
534  * \brief Determines whether execution of a custom function's read function
535  * is allowed.
536  *
537  * \param acfptr Custom function to check
538  * \return True (non-zero) if reading is allowed.
539  * \return False (zero) if reading is not allowed.
540  */
541 static int is_read_allowed(struct ast_custom_function *acfptr)
542 {
543  if (!acfptr) {
544  return 1;
545  }
546 
547  if (!read_escalates(acfptr)) {
548  return 1;
549  }
550 
552  return 1;
553  }
554 
555  if (live_dangerously) {
556  /* Global setting overrides the thread's preference */
557  ast_debug(2, "Reading %s from a dangerous context\n",
558  acfptr->name);
559  return 1;
560  }
561 
562  /* We have no reason to allow this function to execute */
563  return 0;
564 }
565 
566 /*!
567  * \brief Determines whether execution of a custom function's write function
568  * is allowed.
569  *
570  * \param acfptr Custom function to check
571  * \return True (non-zero) if writing is allowed.
572  * \return False (zero) if writing is not allowed.
573  */
574 static int is_write_allowed(struct ast_custom_function *acfptr)
575 {
576  if (!acfptr) {
577  return 1;
578  }
579 
580  if (!write_escalates(acfptr)) {
581  return 1;
582  }
583 
585  return 1;
586  }
587 
588  if (live_dangerously) {
589  /* Global setting overrides the thread's preference */
590  ast_debug(2, "Writing %s from a dangerous context\n",
591  acfptr->name);
592  return 1;
593  }
594 
595  /* We have no reason to allow this function to execute */
596  return 0;
597 }
598 
599 int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
600 {
601  char *copy = ast_strdupa(function);
602  char *args = func_args(copy);
603  struct ast_custom_function *acfptr = ast_custom_function_find(copy);
604  int res;
605  struct ast_module_user *u = NULL;
606 
607  if (acfptr == NULL) {
608  ast_log(LOG_ERROR, "Function %s not registered\n", copy);
609  } else if (!acfptr->read && !acfptr->read2) {
610  ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
611  } else if (!is_read_allowed(acfptr)) {
612  ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
613  } else if (acfptr->read) {
614  if (acfptr->mod) {
615  u = __ast_module_user_add(acfptr->mod, chan);
616  }
617  res = acfptr->read(chan, copy, args, workspace, len);
618  if (acfptr->mod && u) {
619  __ast_module_user_remove(acfptr->mod, u);
620  }
621 
622  return res;
623  } else {
624  struct ast_str *str = ast_str_create(16);
625 
626  if (acfptr->mod) {
627  u = __ast_module_user_add(acfptr->mod, chan);
628  }
629  res = acfptr->read2(chan, copy, args, &str, 0);
630  if (acfptr->mod && u) {
631  __ast_module_user_remove(acfptr->mod, u);
632  }
633  ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
634  ast_free(str);
635 
636  return res;
637  }
638 
639  return -1;
640 }
641 
642 int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
643 {
644  char *copy = ast_strdupa(function);
645  char *args = func_args(copy);
646  struct ast_custom_function *acfptr = ast_custom_function_find(copy);
647  int res;
648  struct ast_module_user *u = NULL;
649 
650  if (acfptr == NULL) {
651  ast_log(LOG_ERROR, "Function %s not registered\n", copy);
652  } else if (!acfptr->read && !acfptr->read2) {
653  ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
654  } else if (!is_read_allowed(acfptr)) {
655  ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
656  } else {
657  if (acfptr->mod) {
658  u = __ast_module_user_add(acfptr->mod, chan);
659  }
660  ast_str_reset(*str);
661  if (acfptr->read2) {
662  /* ast_str enabled */
663  res = acfptr->read2(chan, copy, args, str, maxlen);
664  } else {
665  /* Legacy function pointer, allocate buffer for result */
666  int maxsize = ast_str_size(*str);
667 
668  if (maxlen > -1) {
669  if (maxlen == 0) {
670  if (acfptr->read_max) {
671  maxsize = acfptr->read_max;
672  } else {
673  maxsize = VAR_BUF_SIZE;
674  }
675  } else {
676  maxsize = maxlen;
677  }
678  ast_str_make_space(str, maxsize);
679  }
680  res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
681  }
682  if (acfptr->mod && u) {
683  __ast_module_user_remove(acfptr->mod, u);
684  }
685 
686  return res;
687  }
688 
689  return -1;
690 }
691 
692 int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
693 {
694  char *copy = ast_strdupa(function);
695  char *args = func_args(copy);
696  struct ast_custom_function *acfptr = ast_custom_function_find(copy);
697 
698  if (acfptr == NULL) {
699  ast_log(LOG_ERROR, "Function %s not registered\n", copy);
700  } else if (!acfptr->write) {
701  ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
702  } else if (!is_write_allowed(acfptr)) {
703  ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy);
704  } else {
705  int res;
706  struct ast_module_user *u = NULL;
707 
708  if (acfptr->mod) {
709  u = __ast_module_user_add(acfptr->mod, chan);
710  }
711  res = acfptr->write(chan, copy, args, value);
712  if (acfptr->mod && u) {
713  __ast_module_user_remove(acfptr->mod, u);
714  }
715 
716  return res;
717  }
718 
719  return -1;
720 }
721 
722 static struct ast_cli_entry acf_cli[] = {
723  AST_CLI_DEFINE(handle_show_functions, "Shows registered dialplan functions"),
724  AST_CLI_DEFINE(handle_show_function, "Describe a specific dialplan function"),
725 };
726 
727 static void unload_pbx_functions_cli(void)
728 {
729  ast_cli_unregister_multiple(acf_cli, ARRAY_LEN(acf_cli));
730 }
731 
733 {
734  ast_cli_register_multiple(acf_cli, ARRAY_LEN(acf_cli));
736 
737  return 0;
738 }
const char * name
Definition: pbx.h:119
static const char synopsis[]
Definition: app_mysql.c:64
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Definition: threadstorage.h:84
int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
Register a custom function.
Main Channel structure associated with a channel.
int ast_thread_inhibit_escalations(void)
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations...
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
executes a write operation on a function
Asterisk main include file. File version handling, generic pbx functions.
int ast_thread_inhibit_escalations_swap(int inhibit)
Swap the current thread escalation inhibit setting.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
static char * handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Private include file for pbx.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: linkedlists.h:332
static int live_dangerously
Set to true (non-zero) to globally allow all dangerous dialplan functions to run. ...
Definition: pbx_functions.c:46
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:699
const ast_string_field syntax
Definition: pbx.h:126
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
static int is_read_allowed(struct ast_custom_function *acfptr)
Determines whether execution of a custom function&#39;s read function is allowed.
descriptor for a cli entry.
Definition: cli.h:171
const int argc
Definition: cli.h:160
#define LOG_WARNING
Definition: logger.h:274
#define ast_str_make_space(buf, new_len)
Definition: strings.h:780
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
void __ast_module_user_remove(struct ast_module *, struct ast_module_user *)
Definition: loader.c:826
ast_custom_function_escalation
Description of the ways in which a function may escalate privileges.
Definition: pbx.h:1498
#define COLOR_CYAN
Definition: term.h:59
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
char * ast_xmldoc_build_description(const char *type, const char *name, const char *module)
Generate description documentation from XML.
Definition: xmldoc.c:2250
const ast_string_field desc
Definition: pbx.h:126
enum ast_doc_src docsrc
Definition: pbx.h:127
Definition: cli.h:152
static const char desc[]
Definition: cdr_mysql.c:73
static char * handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx_functions.c:61
const ast_string_field arguments
Definition: pbx.h:126
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static int copy(char *infile, char *outfile)
Utility function to copy a file.
static struct ast_custom_function * ast_custom_function_find_nolock(const char *name)
struct ast_module * mod
Definition: pbx.h:142
static int is_write_allowed(struct ast_custom_function *acfptr)
Determines whether execution of a custom function&#39;s write function is allowed.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
const char * str
Definition: app_jack.c:147
const char * args
int __ast_custom_function_register_escalating(struct ast_custom_function *acf, enum ast_custom_function_escalation escalation, struct ast_module *mod)
Register a custom function which requires escalated privileges.
#define NULL
Definition: resample.c:96
Definitions to aid in the use of thread local storage.
unsigned int write_escalates
Definition: pbx.h:147
char * ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
Generate synopsis documentation from XML.
Definition: xmldoc.c:2227
int value
Definition: syslog.c:37
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
char * ast_xmldoc_build_arguments(const char *type, const char *name, const char *module)
Generate the [arguments] tag based on type of node (&#39;application&#39;, &#39;function&#39; or &#39;agi&#39;) and name...
Definition: xmldoc.c:2075
#define ast_verb(level,...)
Definition: logger.h:463
#define COLOR_BRCYAN
Definition: term.h:60
#define COLORIZE(fg, bg, str)
Definition: term.h:68
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define AST_TERM_MAX_ESCAPE_CHARS
Maximum number of characters needed for a color escape sequence, and another one for a trailing reset...
Definition: term.h:71
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static int thread_inhibits_escalations(void)
Indicates whether the current thread inhibits the execution of dangerous functions.
static void unload_pbx_functions_cli(void)
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
const int fd
Definition: cli.h:159
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
const int n
Definition: cli.h:165
static char * func_args(char *function)
return a pointer to the arguments of the function, and terminates the function name with &#39;\0&#39; ...
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
unsigned int read_escalates
Definition: pbx.h:143
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Definition: term.h:67
size_t read_max
Definition: pbx.h:139
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
Registered functions container.
Definition: pbx_functions.c:59
ast_acf_write_fn_t write
Definition: pbx.h:141
A set of macros to manage forward-linked lists.
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:609
Core PBX routines and definitions.
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
static char * complete_functions(const char *word, int pos, int state)
static int acf_retrieve_docs(struct ast_custom_function *acf)
struct ast_module_user * __ast_module_user_add(struct ast_module *, struct ast_channel *)
Definition: loader.c:800
struct ast_channel * chan
Definition: loader.c:128
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:184
const char *const * argv
Definition: cli.h:161
#define LOG_ERROR
Definition: logger.h:285
ast_acf_read2_fn_t read2
Definition: pbx.h:137
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define AST_MAX_APP
Definition: pbx.h:40
void pbx_live_dangerously(int new_live_dangerously)
Enable/disable the execution of &#39;dangerous&#39; functions from external protocols (AMI, etc.).
#define CLI_SHOWUSAGE
Definition: cli.h:45
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
def info(msg)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static struct ast_cli_entry acf_cli[]
#define LOG_NOTICE
Definition: logger.h:263
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int load_pbx_functions_cli(void)
#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
static int write_escalates(const struct ast_custom_function *acf)
Returns true if given custom function escalates privileges on write.
static int maxsize
static int read_escalates(const struct ast_custom_function *acf)
Returns true if given custom function escalates privileges on read.
struct ast_custom_function * ast_custom_function_find(const char *name)
Asterisk XML Documentation API.
const char * word
Definition: cli.h:163
Prototypes for public functions only of internal interest,.
char * ast_xmldoc_printable(const char *bwinput, int withcolors)
Colorize and put delimiters (instead of tags) to the xmldoc output.
Definition: xmldoc.c:242
const ast_string_field synopsis
Definition: pbx.h:126
char * ast_xmldoc_build_syntax(const char *type, const char *name, const char *module)
Get the syntax for a specified application or function.
Definition: xmldoc.c:1253
char * ast_xmldoc_build_seealso(const char *type, const char *name, const char *module)
Parse the <see-also> node content.
Definition: xmldoc.c:1698
const char * usage
Definition: cli.h:177
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
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
const char * ast_module_name(const struct ast_module *mod)
Get the name of a module.
Definition: loader.c:615
Standard Command Line Interface.
ast_acf_read_fn_t read
Definition: pbx.h:129
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const int pos
Definition: cli.h:164
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:884
Handy terminal functions for vt* terms.
static struct ast_threadstorage thread_inhibit_escalations_tl
Definition: pbx_functions.c:46
const ast_string_field seealso
Definition: pbx.h:126
Asterisk module definitions.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616
#define COLOR_MAGENTA
Definition: term.h:57
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
short word
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
static struct test_val a