69 e->
command =
"core show functions [like]";
71 "Usage: core show functions [like <text>]\n"
72 " List builtin functions, optionally only those matching a given string\n";
78 if (a->argc == 5 && (!strcmp(a->argv[3],
"like")) ) {
80 }
else if (a->argc != 3) {
84 ast_cli(a->fd,
"%s Custom Functions:\n"
85 "--------------------------------------------------------------------------------\n",
86 like ?
"Matching" :
"Installed");
89 AST_RWLIST_TRAVERSE(&
acf_root, acf, acflist) {
90 if (!like || strstr(acf->
name, a->argv[4])) {
92 ast_cli(a->fd,
"%-20.20s %-35.35s %s\n",
100 ast_cli(a->fd,
"%d %scustom functions installed.\n", count_acf, like ?
"matching " :
"");
105 static char *complete_functions(
const char *word,
int pos,
int state)
117 wordlen = strlen(word);
119 AST_RWLIST_TRAVERSE(&
acf_root, cur, acflist) {
127 cmp = strncasecmp(word, cur->
name, wordlen);
130 if (++which <= state) {
147 char infotitle[64 +
AST_MAX_APP + 22], syntitle[40], desctitle[40], argtitle[40], seealsotitle[40];
150 int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
154 e->
command =
"core show function";
156 "Usage: core show function <function>\n"
157 " Describe a particular dialplan function.\n";
160 return complete_functions(a->word, a->pos, a->n);
164 return CLI_SHOWUSAGE;
167 if (!(acf = ast_custom_function_find(a->argv[3]))) {
168 ast_cli(a->fd,
"No function by that name registered.\n");
176 ast_cli(a->fd,
"Memory allocation failure!\n");
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(desctitle,
"[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);
211 if (!synopsis || !description || !arguments || !seealso) {
213 ast_free(description);
223 term_color(description,
S_OR(acf->
desc,
"Not available"), COLOR_CYAN, 0, description_size);
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, desctitle, description,
229 stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
233 ast_free(description);
245 AST_RWLIST_TRAVERSE(&
acf_root, cur, acflist) {
246 cmp = strcmp(name, cur->
name);
267 acf = ast_custom_function_find_nolock(name);
282 cur = AST_RWLIST_REMOVE(&
acf_root, acf, acflist);
289 ast_verb(5,
"Unregistered custom function %s\n", cur->
name);
334 if (!ast_strlen_zero(acf->
desc) || !ast_strlen_zero(acf->
synopsis)) {
386 if (acf_retrieve_docs(acf)) {
392 cur = ast_custom_function_find_nolock(acf->
name);
394 ast_log(LOG_ERROR,
"Function %s already registered.\n", acf->
name);
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);
406 AST_RWLIST_TRAVERSE_SAFE_END;
408 AST_RWLIST_INSERT_TAIL(&
acf_root, acf, acflist);
413 ast_verb(5,
"Registered custom function '" COLORIZE_FMT "'\n", COLORIZE(COLOR_BRCYAN, 0, acf->
name));
427 switch (escalation) {
450 char *args = strchr(
function,
'(');
453 ast_log(LOG_WARNING,
"Function '%s' doesn't contain parentheses. Assuming null argument.\n",
function);
457 if ((p = strrchr(args,
')'))) {
460 ast_log(LOG_WARNING,
"Can't find trailing parenthesis for function '%s(%s'?\n",
function, args);
469 ast_log(LOG_WARNING,
"Privilege escalation protection disabled!\n"
470 "See https://docs.asterisk.org/Configuration/Dialplan/Privilege-Escalations-with-Dialplan-Functions/ for more details.\n");
474 ast_log(LOG_NOTICE,
"Privilege escalation protection enabled.\n");
481 int *thread_inhibit_escalations;
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");
490 *thread_inhibit_escalations = 1;
496 int *thread_inhibit_escalations;
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");
506 orig = *thread_inhibit_escalations;
507 *thread_inhibit_escalations = !!inhibit;
520 int *thread_inhibit_escalations;
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");
530 return *thread_inhibit_escalations;
557 ast_debug(2,
"Reading %s from a dangerous context\n",
590 ast_debug(2,
"Writing %s from a dangerous context\n",
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);
612 ast_log(LOG_ERROR,
"Dangerous function %s read blocked\n", copy);
613 }
else if (acfptr->
read) {
615 u = __ast_module_user_add(acfptr->
mod, chan);
617 res = acfptr->
read(chan, copy, args, workspace, len);
618 if (acfptr->
mod && u) {
619 __ast_module_user_remove(acfptr->
mod, u);
627 u = __ast_module_user_add(acfptr->
mod, chan);
629 res = acfptr->
read2(chan, copy, args, &str, 0);
630 if (acfptr->
mod && u) {
631 __ast_module_user_remove(acfptr->
mod, u);
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);
655 ast_log(LOG_ERROR,
"Dangerous function %s read blocked\n", copy);
658 u = __ast_module_user_add(acfptr->
mod, chan);
663 res = acfptr->
read2(chan, copy, args, str, maxlen);
673 maxsize = VAR_BUF_SIZE;
678 ast_str_make_space(str, maxsize);
683 if (acfptr->
mod && u) {
684 __ast_module_user_remove(acfptr->
mod, u);
699 if (acfptr == NULL) {
700 ast_log(LOG_ERROR,
"Function %s not registered\n", copy);
701 }
else if (!acfptr->
write) {
702 ast_log(LOG_ERROR,
"Function %s cannot be written to\n", copy);
704 ast_log(LOG_ERROR,
"Dangerous function %s write blocked\n", copy);
710 u = __ast_module_user_add(acfptr->
mod, chan);
712 res = acfptr->
write(chan, copy, args, value);
713 if (acfptr->
mod && u) {
714 __ast_module_user_remove(acfptr->
mod, u);
724 AST_CLI_DEFINE(handle_show_functions,
"Shows registered dialplan functions"),
725 AST_CLI_DEFINE(handle_show_function,
"Describe a specific dialplan function"),
728 static void unload_pbx_functions_cli(
void)
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
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...
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.
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
Private include file for pbx.
static int live_dangerously
Set to true (non-zero) to globally allow all dangerous dialplan functions to run. ...
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
const ast_string_field syntax
static int is_read_allowed(struct ast_custom_function *acfptr)
Determines whether execution of a custom function's read function is allowed.
descriptor for a cli entry.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
ast_custom_function_escalation
Description of the ways in which a function may escalate privileges.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
char * ast_xmldoc_build_description(const char *type, const char *name, const char *module)
Generate description documentation from XML.
const ast_string_field desc
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
const ast_string_field arguments
#define ast_cli_register_multiple(e, len)
Register multiple commands.
static int copy(char *infile, char *outfile)
Utility function to copy a file.
static int is_write_allowed(struct ast_custom_function *acfptr)
Determines whether execution of a custom function's write function is allowed.
#define ast_strdup(str)
A wrapper for strdup()
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.
Definitions to aid in the use of thread local storage.
unsigned int write_escalates
char * ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
Generate synopsis documentation from XML.
char * ast_xmldoc_build_arguments(const char *type, const char *name, const char *module)
Generate the [arguments] tag based on type of node ('application', 'function' or 'agi') and name...
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
#define AST_TERM_MAX_ESCAPE_CHARS
Maximum number of characters needed for a color escape sequence, and another one for a trailing reset...
static int thread_inhibits_escalations(void)
Indicates whether the current thread inhibits the execution of dangerous functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_strdupa(s)
duplicate a string in memory from the stack
static char * func_args(char *function)
return a pointer to the arguments of the function, and terminates the function name with '\0' ...
Data structure associated with a custom dialplan function.
unsigned int read_escalates
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Registered functions container.
A set of macros to manage forward-linked lists.
#define ast_malloc(len)
A wrapper for malloc()
#define ast_debug(level,...)
Log a DEBUG message.
Core PBX routines and definitions.
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Support for dynamic strings.
void pbx_live_dangerously(int new_live_dangerously)
Enable/disable the execution of 'dangerous' functions from external protocols (AMI, etc.).
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
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int load_pbx_functions_cli(void)
static int write_escalates(const struct ast_custom_function *acf)
Returns true if given custom function escalates privileges on write.
static int read_escalates(const struct ast_custom_function *acf)
Returns true if given custom function escalates privileges on read.
Asterisk XML Documentation API.
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.
const ast_string_field synopsis
char * ast_xmldoc_build_syntax(const char *type, const char *name, const char *module)
Get the syntax for a specified application or function.
char * ast_xmldoc_build_seealso(const char *type, const char *name, const char *module)
Parse the node content.
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
const char * ast_module_name(const struct ast_module *mod)
Get the name of a module.
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Handy terminal functions for vt* terms.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
const ast_string_field seealso
Asterisk module definitions.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
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_str_create(init_len)
Create a malloc'ed dynamic length string.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.