Asterisk - The Open Source Telephony Project GIT-master-0a46be9
Data Structures | Macros | Functions | Variables
main/cli.c File Reference

Standard Command Line Interface. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <signal.h>
#include <ctype.h>
#include <regex.h>
#include <pwd.h>
#include <grp.h>
#include "asterisk/cli.h"
#include "asterisk/linkedlists.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/lock.h"
#include "asterisk/threadstorage.h"
#include "asterisk/logger_category.h"
#include "asterisk/translate.h"
#include "asterisk/bridge.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/vector.h"
#include "asterisk/stream.h"
Include dependency graph for main/cli.c:

Go to the source code of this file.

Data Structures

struct  channel_set_debug_args
 
struct  cli_perm
 List of restrictions per user. More...
 
struct  cli_perm_head
 
struct  cli_perms
 List of users and permissions. More...
 
struct  helpers
 
struct  module_level
 map a debug or verbose level to a module name More...
 
struct  module_level_list
 
struct  usergroup_cli_perm
 list of users to apply restrictions. More...
 

Macros

#define AST_CLI_INITLEN   256
 Initial buffer size for resulting strings in ast_cli() More...
 
#define CONCISE_FORMAT_STRING   "%s!%s!%s!%d!%s!%s!%s!%s!%s!%s!%d!%s!%s!%s\n"
 
#define DAY   (HOUR*24)
 
#define DEBUG_HANDLER   0
 
#define FORMAT_STRING   "%-64.64s %-32.32s %-7.7s %-30.30s\n"
 
#define FORMAT_STRING   "%-25s %-20s %-20s\n"
 
#define FORMAT_STRING2   "%-64.64s %-32.32s %-7.7s %-30.30s\n"
 
#define HOUR   (MINUTE*60)
 
#define MINUTE   (SECOND*60)
 
#define MODLIST_FORMAT   "%-30s %-40.40s %-10d %-11s %13s\n"
 
#define MODLIST_FORMAT2   "%-30s %-40.40s %-10s %-11s %13s\n"
 
#define NEEDCOMMA(x)   ((x) ? ", " : "") /* define if we need a comma */
 
#define SECOND   (1)
 
#define TRACE_HANDLER   1
 
#define VERBOSE_FORMAT_STRING   "%-80.80s %-24.24s %-24.24s %4d %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-11.11s %-20.20s\n"
 
#define VERBOSE_FORMAT_STRING2   "%-80.80s %-24.24s %-24.24s %-4.4s %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-11.11s %-20.20s\n"
 
#define VERBOSE_HANDLER   2
 
#define WEEK   (DAY*7)
 
#define YEAR   (DAY*365)
 

Functions

static char * __ast_cli_generator (const char *text, const char *word, int state, int lock)
 
int __ast_cli_register (struct ast_cli_entry *e, struct ast_module *module)
 
int __ast_cli_register_multiple (struct ast_cli_entry *e, int len, struct ast_module *module)
 
static void __init_ast_cli_buf (void)
 
static int allowed_on_shutdown (struct ast_cli_entry *e)
 
void ast_builtins_init (void)
 initialize the _full_cmd string in * each of the builtins. More...
 
void ast_cli (int fd, const char *fmt,...)
 
int ast_cli_allow_at_shutdown (struct ast_cli_entry *e)
 Allow a CLI command to be executed while Asterisk is shutting down. More...
 
void ast_cli_channels_init (void)
 
int ast_cli_command_full (int uid, int gid, int fd, const char *s)
 Interprets a command Interpret a command s, sending output to fd if uid:gid has permissions to run this command. uid = CLI_NO_PERMS to avoid checking user permissions gid = CLI_NO_PERMS to avoid checking group permissions. More...
 
int ast_cli_command_multiple_full (int uid, int gid, int fd, size_t size, const char *s)
 Executes multiple CLI commands Interpret strings separated by NULL and execute each one, sending output to fd if uid has permissions, uid = CLI_NO_PERMS to avoid checking users permissions. gid = CLI_NO_PERMS to avoid checking group permissions. More...
 
char * ast_cli_complete (const char *word, const char *const choices[], int state)
 
int ast_cli_completion_add (char *value)
 Add a result to a request for completion options. More...
 
char ** ast_cli_completion_matches (const char *text, const char *word)
 Generates a NULL-terminated array of strings that 1) begin with the string in the second parameter, and 2) are valid in a command after the string in the first parameter. More...
 
struct ast_vector_stringast_cli_completion_vector (const char *text, const char *word)
 Generates a vector of strings for CLI completion. More...
 
char * ast_cli_generator (const char *text, const char *word, int state)
 Readline madness Useful for readline, that's about it. More...
 
int ast_cli_perms_init (int reload)
 
void ast_cli_print_timestr_fromseconds (int fd, int seconds, const char *prefix)
 Print on cli a duration in seconds in format s year(s), s week(s), s day(s), s hour(s), s second(s) More...
 
int ast_cli_unregister (struct ast_cli_entry *e)
 Unregisters a command or an array of commands. More...
 
int ast_cli_unregister_multiple (struct ast_cli_entry *e, int len)
 Unregister multiple commands. More...
 
char * ast_complete_channels (const char *line, const char *word, int pos, int state, int rpos)
 Command completion for the list of active channels. More...
 
unsigned int ast_debug_get_by_module (const char *module)
 Get the debug level for a module. More...
 
 AST_THREADSTORAGE_RAW (completion_storage)
 
unsigned int ast_trace_get_by_module (const char *module)
 Get the trace level for a module. More...
 
static int channel_set_debug (void *obj, void *arg, void *data, int flags)
 
static void cli_channels_shutdown (void)
 
static int cli_completion_vector_add (struct ast_vector_string *vec, char *value)
 
static int cli_has_permissions (int uid, int gid, const char *command)
 
static int cli_is_registered (struct ast_cli_entry *e)
 
static struct ast_cli_entrycli_next (struct ast_cli_entry *e)
 
static void cli_shutdown (void)
 
static char * complete_number (const char *partial, unsigned int min, unsigned int max, int n)
 
static void destroy_user_perms (void)
 cleanup (free) cli_perms linkedlist. More...
 
static char * find_best (const char *argv[])
 
static struct ast_cli_entryfind_cli (const char *const cmds[], int match_type)
 
static struct module_levelfind_module_level (const char *module, struct module_level_list *mll)
 Find the module level setting. More...
 
static char * group_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_chanlist (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_check_permissions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handles CLI command 'cli check permissions' More...
 
static char * handle_cli_malloc_trim (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_reload_permissions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handles CLI command 'cli reload permissions' More...
 
static char * handle_cli_show_permissions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handles CLI command 'cli show permissions' More...
 
static char * handle_cli_wait_fullybooted (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_commandmatchesarray (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_core_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_core_set_debug_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_debug_category (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_debug_or_trace (int handler, struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_help (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_load (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_logger_mute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_modlist (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_refresh (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_showcalls (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_showchan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_showuptime (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_softhangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_trace (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_unload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_verbose (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * help1 (int fd, const char *const match[], int locked)
 helper for final part of handle_help if locked = 1, assume the list is already locked More...
 
static char * is_prefix (const char *word, const char *token, int pos, int *actual)
 if word is a valid prefix for token, returns the pos-th match as a malloced string, or NULL otherwise. Always tell in *actual how many matches we got. More...
 
static int modlist_modentry (const char *module, const char *description, int usecnt, const char *status, const char *like, enum ast_module_support_level support_level)
 
static int more_words (const char *const *dst)
 returns true if there are more words to match More...
 
static char * parse_args (const char *s, int *argc, const char *argv[], int max, int *trailingwhitespace)
 
static void print_uptimestr (int fd, struct timeval timeval, const char *prefix, int printsec)
 
static void remove_shutdown_command (struct ast_cli_entry *e)
 
static int set_full_cmd (struct ast_cli_entry *e)
 
static void status_debug_verbose (struct ast_cli_args *a, int handler, int old_val, int cur_val)
 
static int word_match (const char *cmd, const char *cli_word)
 

Variables

static struct ast_threadstorage ast_cli_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_ast_cli_buf , .custom_init = NULL , }
 
static struct ast_cli_entry cli_channels_cli []
 
static struct ast_cli_entry cli_cli []
 
static int cli_default_perm = 1
 Default permissions value 1=Permit 0=Deny. More...
 
static struct cli_perms cli_perms = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static const char cli_rsvd [] = "[]{}|*%"
 
static int climodentryfd = -1
 
static ast_mutex_t climodentrylock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static struct module_level_list debug_modules = AST_RWLIST_HEAD_INIT_VALUE
 
static struct helpers helpers = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static const char perms_config [] = "cli_permissions.conf"
 CLI permissions config file. More...
 
static ast_mutex_t permsconfiglock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 mutex used to prevent a user from running the 'cli reload permissions' command while it is already running. More...
 
struct {
   size_t   current
 
   struct ast_cli_entry **   elems
 
   size_t   max
 
shutdown_commands
 
static ast_rwlock_t shutdown_commands_lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} }
 
static struct module_level_list trace_modules = AST_RWLIST_HEAD_INIT_VALUE
 

Detailed Description

Standard Command Line Interface.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file main/cli.c.

Macro Definition Documentation

◆ AST_CLI_INITLEN

#define AST_CLI_INITLEN   256

Initial buffer size for resulting strings in ast_cli()

Definition at line 116 of file main/cli.c.

◆ CONCISE_FORMAT_STRING

#define CONCISE_FORMAT_STRING   "%s!%s!%s!%d!%s!%s!%s!%s!%s!%s!%d!%s!%s!%s\n"

◆ DAY

#define DAY   (HOUR*24)

◆ DEBUG_HANDLER

#define DEBUG_HANDLER   0

Definition at line 403 of file main/cli.c.

◆ FORMAT_STRING [1/2]

#define FORMAT_STRING   "%-64.64s %-32.32s %-7.7s %-30.30s\n"

◆ FORMAT_STRING [2/2]

#define FORMAT_STRING   "%-25s %-20s %-20s\n"

◆ FORMAT_STRING2

#define FORMAT_STRING2   "%-64.64s %-32.32s %-7.7s %-30.30s\n"

◆ HOUR

#define HOUR   (MINUTE*60)

◆ MINUTE

#define MINUTE   (SECOND*60)

◆ MODLIST_FORMAT

#define MODLIST_FORMAT   "%-30s %-40.40s %-10d %-11s %13s\n"

Definition at line 894 of file main/cli.c.

◆ MODLIST_FORMAT2

#define MODLIST_FORMAT2   "%-30s %-40.40s %-10s %-11s %13s\n"

Definition at line 895 of file main/cli.c.

◆ NEEDCOMMA

#define NEEDCOMMA (   x)    ((x) ? ", " : "") /* define if we need a comma */

◆ SECOND

#define SECOND   (1)

◆ TRACE_HANDLER

#define TRACE_HANDLER   1

Definition at line 404 of file main/cli.c.

◆ VERBOSE_FORMAT_STRING

#define VERBOSE_FORMAT_STRING   "%-80.80s %-24.24s %-24.24s %4d %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-11.11s %-20.20s\n"

◆ VERBOSE_FORMAT_STRING2

#define VERBOSE_FORMAT_STRING2   "%-80.80s %-24.24s %-24.24s %-4.4s %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-11.11s %-20.20s\n"

◆ VERBOSE_HANDLER

#define VERBOSE_HANDLER   2

Definition at line 405 of file main/cli.c.

◆ WEEK

#define WEEK   (DAY*7)

◆ YEAR

#define YEAR   (DAY*365)

Function Documentation

◆ __ast_cli_generator()

static char * __ast_cli_generator ( const char *  text,
const char *  word,
int  state,
int  lock 
)
static

Definition at line 2840 of file main/cli.c.

2841{
2842 const char *argv[AST_MAX_ARGS];
2843 struct ast_cli_entry *e = NULL;
2844 int x = 0, argindex, matchlen;
2845 int matchnum=0;
2846 char *ret = NULL;
2847 char matchstr[80] = "";
2848 int tws = 0;
2849 /* Split the argument into an array of words */
2850 char *duplicate = parse_args(text, &x, argv, ARRAY_LEN(argv), &tws);
2851
2852 if (!duplicate) /* malloc error */
2853 return NULL;
2854
2855 /* Compute the index of the last argument (could be an empty string) */
2856 argindex = (!ast_strlen_zero(word) && x>0) ? x-1 : x;
2857
2858 /* rebuild the command, ignore terminating white space and flatten space */
2859 ast_join(matchstr, sizeof(matchstr)-1, argv);
2860 matchlen = strlen(matchstr);
2861 if (tws) {
2862 strcat(matchstr, " "); /* XXX */
2863 if (matchlen)
2864 matchlen++;
2865 }
2866 if (lock)
2868 while ( (e = cli_next(e)) ) {
2869 /* XXX repeated code */
2870 int src = 0, dst = 0, n = 0;
2871
2872 if (e->command[0] == '_')
2873 continue;
2874
2875 /*
2876 * Try to match words, up to and excluding the last word, which
2877 * is either a blank or something that we want to extend.
2878 */
2879 for (;src < argindex; dst++, src += n) {
2880 n = word_match(argv[src], e->cmda[dst]);
2881 if (n < 0)
2882 break;
2883 }
2884
2885 if (src != argindex && more_words(e->cmda + dst)) /* not a match */
2886 continue;
2887 ret = is_prefix(argv[src], e->cmda[dst], state - matchnum, &n);
2888 matchnum += n; /* this many matches here */
2889 if (ret) {
2890 /*
2891 * argv[src] is a valid prefix of the next word in this
2892 * command. If this is also the correct entry, return it.
2893 */
2894 if (matchnum > state)
2895 break;
2896 ast_free(ret);
2897 ret = NULL;
2898 } else if (ast_strlen_zero(e->cmda[dst])) {
2899 /*
2900 * This entry is a prefix of the command string entered
2901 * (only one entry in the list should have this property).
2902 * Run the generator if one is available. In any case we are done.
2903 */
2904 if (e->handler) { /* new style command */
2905 struct ast_cli_args a = {
2906 .line = matchstr, .word = word,
2907 .pos = argindex,
2908 .n = state - matchnum,
2909 .argv = argv,
2910 .argc = x};
2911
2912 /* If the command is in a module it must be running. */
2913 if (!e->module || ast_module_running_ref(e->module)) {
2914 ret = e->handler(e, CLI_GENERATE, &a);
2916 }
2917 }
2918 if (ret)
2919 break;
2920 }
2921 }
2922 if (lock)
2924 ast_free(duplicate);
2925 return ret;
2926}
char * text
Definition: app_queue.c:1765
ast_mutex_t lock
Definition: app_sla.c:337
#define ast_free(a)
Definition: astmm.h:180
#define AST_MAX_ARGS
Definition: cli.h:50
@ CLI_GENERATE
Definition: cli.h:153
short word
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
static int word_match(const char *cmd, const char *cli_word)
Definition: main/cli.c:2238
static int more_words(const char *const *dst)
returns true if there are more words to match
Definition: main/cli.c:2827
static char * is_prefix(const char *word, const char *token, int pos, int *actual)
if word is a valid prefix for token, returns the pos-th match as a malloced string,...
Definition: main/cli.c:2277
static struct ast_cli_entry * cli_next(struct ast_cli_entry *e)
Definition: main/cli.c:966
static char * parse_args(const char *s, int *argc, const char *argv[], int max, int *trailingwhitespace)
Definition: main/cli.c:2609
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition: module.h:469
#define NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_join(s, len, w)
Join an array of strings into a single string.
Definition: strings.h:520
const char *const * argv
Definition: cli.h:161
descriptor for a cli entry.
Definition: cli.h:171
char *(* handler)(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: cli.h:187
struct ast_module * module
Definition: cli.h:180
const char *const cmda[AST_MAX_CMD_LEN]
Definition: cli.h:172
char * command
Definition: cli.h:186
static struct test_val a
#define ARRAY_LEN(a)
Definition: utils.h:703

References a, ast_cli_args::argv, ARRAY_LEN, ast_free, ast_join, AST_MAX_ARGS, ast_module_running_ref, ast_module_unref, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_strlen_zero(), CLI_GENERATE, cli_next(), ast_cli_entry::cmda, ast_cli_entry::command, ast_cli_entry::handler, is_prefix(), lock, ast_cli_entry::module, more_words(), NULL, parse_args(), text, and word_match().

Referenced by ast_cli_generator(), and handle_help().

◆ __ast_cli_register()

int __ast_cli_register ( struct ast_cli_entry e,
struct ast_module module 
)

Definition at line 2431 of file main/cli.c.

2432{
2433 struct ast_cli_entry *cur;
2434 int i, lf, ret = -1;
2435
2436 struct ast_cli_args a; /* fake argument */
2437 char **dst = (char **)e->cmda; /* need to cast as the entry is readonly */
2438 char *s;
2439
2441
2442 if (cli_is_registered(e)) {
2443 ast_log(LOG_WARNING, "Command '%s' already registered (the same ast_cli_entry)\n",
2444 S_OR(e->_full_cmd, e->command));
2445 ret = 0; /* report success */
2446 goto done;
2447 }
2448
2449 memset(&a, '\0', sizeof(a));
2450
2451 e->module = module;
2452 /* No module reference needed here, the module called us. */
2453 e->handler(e, CLI_INIT, &a);
2454
2455 /* XXX check that usage and command are filled up */
2456 s = ast_skip_blanks(e->command);
2457 s = e->command = ast_strdup(s);
2458 for (i=0; !ast_strlen_zero(s) && i < AST_MAX_CMD_LEN-1; i++) {
2459 *dst++ = s; /* store string */
2460 s = ast_skip_nonblanks(s);
2461 if (*s == '\0') /* we are done */
2462 break;
2463 *s++ = '\0';
2464 s = ast_skip_blanks(s);
2465 }
2466 *dst++ = NULL;
2467
2468 if (find_cli(e->cmda, 1)) {
2469 ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n",
2470 S_OR(e->_full_cmd, e->command));
2471 goto done;
2472 }
2473 if (set_full_cmd(e)) {
2474 ast_log(LOG_WARNING, "Error registering CLI Command '%s'\n",
2475 S_OR(e->_full_cmd, e->command));
2476 goto done;
2477 }
2478
2479 lf = e->cmdlen;
2481 int len = cur->cmdlen;
2482 if (lf < len)
2483 len = lf;
2484 if (strncasecmp(e->_full_cmd, cur->_full_cmd, len) < 0) {
2486 break;
2487 }
2488 }
2490
2491 if (!cur)
2493 ret = 0; /* success */
2494
2495done:
2497 if (ret) {
2498 ast_free(e->command);
2499 e->command = NULL;
2500 }
2501
2502 return ret;
2503}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_log
Definition: astobj2.c:42
@ CLI_INIT
Definition: cli.h:152
#define AST_MAX_CMD_LEN
Definition: cli.h:48
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define LOG_WARNING
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:610
static struct ast_cli_entry * find_cli(const char *const cmds[], int match_type)
Definition: main/cli.c:2327
static int set_full_cmd(struct ast_cli_entry *e)
Definition: main/cli.c:2046
static int cli_is_registered(struct ast_cli_entry *e)
Definition: main/cli.c:2389
char * ast_skip_nonblanks(const char *str)
Gets a pointer to first whitespace character in a string.
Definition: strings.h:204
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
int cmdlen
Definition: cli.h:182
char * _full_cmd
Definition: cli.h:181
int done
Definition: test_amihooks.c:48

References ast_cli_entry::_full_cmd, a, ast_free, ast_log, AST_MAX_CMD_LEN, AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_skip_blanks(), ast_skip_nonblanks(), ast_strdup, ast_strlen_zero(), CLI_INIT, cli_is_registered(), ast_cli_entry::cmda, ast_cli_entry::cmdlen, ast_cli_entry::command, done, find_cli(), ast_cli_entry::handler, len(), LOG_WARNING, ast_cli_entry::module, NULL, S_OR, and set_full_cmd().

Referenced by __ast_cli_register_multiple().

◆ __ast_cli_register_multiple()

int __ast_cli_register_multiple ( struct ast_cli_entry e,
int  len,
struct ast_module module 
)

Definition at line 2508 of file main/cli.c.

2509{
2510 int i, res = 0;
2511
2512 for (i = 0; i < len; i++) {
2513 res |= __ast_cli_register(e + i, module);
2514 }
2515
2516 return res;
2517}
int __ast_cli_register(struct ast_cli_entry *e, struct ast_module *module)
Definition: main/cli.c:2431

References __ast_cli_register(), and len().

◆ __init_ast_cli_buf()

static void __init_ast_cli_buf ( void  )
static

Definition at line 110 of file main/cli.c.

119{

◆ allowed_on_shutdown()

static int allowed_on_shutdown ( struct ast_cli_entry e)
static

Definition at line 2933 of file main/cli.c.

2934{
2935 int found = 0;
2936 int i;
2937
2939 for (i = 0; i < AST_VECTOR_SIZE(&shutdown_commands); ++i) {
2940 if (e == AST_VECTOR_GET(&shutdown_commands, i)) {
2941 found = 1;
2942 break;
2943 }
2944 }
2946
2947 return found;
2948}
#define ast_rwlock_rdlock(a)
Definition: lock.h:242
#define ast_rwlock_unlock(a)
Definition: lock.h:241
static ast_rwlock_t shutdown_commands_lock
Definition: main/cli.c:112
static struct @337 shutdown_commands
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:620
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:691

References ast_rwlock_rdlock, ast_rwlock_unlock, AST_VECTOR_GET, AST_VECTOR_SIZE, shutdown_commands, and shutdown_commands_lock.

Referenced by ast_cli_command_full().

◆ ast_builtins_init()

void ast_builtins_init ( void  )

initialize the _full_cmd string in * each of the builtins.

Provided by cli.c

Definition at line 2214 of file main/cli.c.

2215{
2219}
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static void cli_shutdown(void)
Definition: main/cli.c:2203
static struct ast_cli_entry cli_cli[]
Definition: main/cli.c:1996
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:124

References ARRAY_LEN, ast_cli_register_multiple, ast_register_cleanup(), AST_VECTOR_INIT, cli_cli, cli_shutdown(), and shutdown_commands.

Referenced by asterisk_daemon().

◆ ast_cli()

void ast_cli ( int  fd,
const char *  fmt,
  ... 
)

Definition at line 118 of file main/cli.c.

119{
120 int res;
121 struct ast_str *buf;
122 va_list ap;
123
125 return;
126
127 va_start(ap, fmt);
128 res = ast_str_set_va(&buf, 0, fmt, ap);
129 va_end(ap);
130
131 if (res != AST_DYNSTR_BUILD_FAILED) {
133 }
134}
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct ast_threadstorage ast_cli_buf
Definition: main/cli.c:110
#define AST_CLI_INITLEN
Initial buffer size for resulting strings in ast_cli()
Definition: main/cli.c:116
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
int ast_str_set_va(struct ast_str **buf, ssize_t max_len, const char *fmt, va_list ap)
Set a dynamic string from a va_list.
Definition: strings.h:1030
@ AST_DYNSTR_BUILD_FAILED
Definition: strings.h:943
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:909
Support for dynamic strings.
Definition: strings.h:623
int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
Try to write string, but wait no more than ms milliseconds before timing out.
Definition: utils.c:1807

References ast_carefulwrite(), ast_cli_buf, AST_CLI_INITLEN, AST_DYNSTR_BUILD_FAILED, ast_str_buffer(), ast_str_set_va(), ast_str_strlen(), ast_str_thread_get(), and buf.

Referenced by ast_cli_command_full(), channel_set_debug(), group_show_channels(), handle_chanlist(), handle_cli_check_permissions(), handle_cli_malloc_trim(), handle_cli_show_permissions(), handle_cli_wait_fullybooted(), handle_commandmatchesarray(), handle_core_set_debug_channel(), handle_debug_or_trace(), handle_help(), handle_load(), handle_modlist(), handle_refresh(), handle_reload(), handle_showcalls(), handle_showchan(), handle_softhangup(), handle_unload(), help1(), modlist_modentry(), print_uptimestr(), and status_debug_verbose().

◆ ast_cli_allow_at_shutdown()

int ast_cli_allow_at_shutdown ( struct ast_cli_entry e)

Allow a CLI command to be executed while Asterisk is shutting down.

CLI commands by defeault are disabled when Asterisk is shutting down. This is to ensure the safety of the shutdown since CLI commands may attempt to access resources that have been freed as a result of the shutdown.

If a CLI command should be allowed at shutdown, then the best way to enable this is to call ast_cli_allow_at_shutdown during the CLI_INIT state of the CLI handler.

Definition at line 3037 of file main/cli.c.

3038{
3039 int res;
3040
3044
3045 return res;
3046}
#define ast_rwlock_wrlock(a)
Definition: lock.h:243
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:267

References ast_rwlock_unlock, ast_rwlock_wrlock, AST_VECTOR_APPEND, shutdown_commands, and shutdown_commands_lock.

Referenced by handle_abort_shutdown(), handle_restart_gracefully(), handle_restart_now(), handle_restart_when_convenient(), handle_stop_gracefully(), handle_stop_now(), and handle_stop_when_convenient().

◆ ast_cli_channels_init()

void ast_cli_channels_init ( void  )

Provided by cli.c

Definition at line 2221 of file main/cli.c.

2222{
2225}
static void cli_channels_shutdown(void)
Definition: main/cli.c:2208
static struct ast_cli_entry cli_channels_cli[]
Definition: main/cli.c:2028

References ARRAY_LEN, ast_cli_register_multiple, ast_register_cleanup(), cli_channels_cli, and cli_channels_shutdown().

Referenced by asterisk_daemon().

◆ ast_cli_command_full()

int ast_cli_command_full ( int  uid,
int  gid,
int  fd,
const char *  s 
)

Interprets a command Interpret a command s, sending output to fd if uid:gid has permissions to run this command. uid = CLI_NO_PERMS to avoid checking user permissions gid = CLI_NO_PERMS to avoid checking group permissions.

Parameters
uidUser ID that is trying to run the command.
gidGroup ID that is trying to run the command.
fdpipe
sincoming string
Return values
0on success
-1on failure

Definition at line 2950 of file main/cli.c.

2951{
2952 const char *args[AST_MAX_ARGS + 1];
2953 struct ast_cli_entry *e = NULL;
2954 int x;
2955 char *duplicate = parse_args(s, &x, args + 1, AST_MAX_ARGS, NULL);
2956 char tmp[AST_MAX_ARGS + 1];
2957 char *retval = CLI_FAILURE;
2958 struct ast_cli_args a = {
2959 .fd = fd, .argc = x, .argv = args+1 };
2960
2961 if (duplicate == NULL)
2962 return RESULT_FAILURE;
2963
2964 if (x < 1) /* We need at least one entry, otherwise ignore */
2965 goto done;
2966
2968 e = find_cli(args + 1, 0);
2969 if (e)
2972 if (e == NULL) {
2973 ast_cli(fd, "No such command '%s' (type 'core show help %s' for other possible commands)\n", s, find_best(args + 1));
2974 goto done;
2975 }
2976
2978 ast_cli(fd, "Command '%s' cannot be run during shutdown\n", s);
2979 goto done;
2980 }
2981
2982 ast_join(tmp, sizeof(tmp), args + 1);
2983 /* Check if the user has rights to run this command. */
2984 if (!cli_has_permissions(uid, gid, tmp)) {
2985 ast_cli(fd, "You don't have permissions to run '%s' command\n", tmp);
2986 goto done;
2987 }
2988
2989 /*
2990 * Within the handler, argv[-1] contains a pointer to the ast_cli_entry.
2991 * Remember that the array returned by parse_args is NULL-terminated.
2992 */
2993 args[0] = (char *)e;
2994
2995 /* If the command is in a module it must be running. */
2996 if (!e->module || ast_module_running_ref(e->module)) {
2997 retval = e->handler(e, CLI_HANDLER, &a);
2999 }
3000
3001 if (retval == CLI_SHOWUSAGE) {
3002 ast_cli(fd, "%s", S_OR(e->usage, "Invalid usage, but no usage information available.\n"));
3003 } else if (retval == CLI_FAILURE) {
3004 ast_cli(fd, "Command '%s' failed.\n", s);
3005 }
3006
3007done:
3008 if (e) {
3010 }
3011 ast_free(duplicate);
3012 return retval == CLI_SUCCESS ? RESULT_SUCCESS : RESULT_FAILURE;
3013}
int ast_shutting_down(void)
Definition: asterisk.c:1888
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
#define RESULT_SUCCESS
Definition: cli.h:40
@ CLI_HANDLER
Definition: cli.h:154
#define CLI_FAILURE
Definition: cli.h:46
#define RESULT_FAILURE
Definition: cli.h:42
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:764
static char * find_best(const char *argv[])
Definition: main/cli.c:2371
void ast_cli(int fd, const char *fmt,...)
Definition: main/cli.c:118
static int allowed_on_shutdown(struct ast_cli_entry *e)
Definition: main/cli.c:2933
static int cli_has_permissions(int uid, int gid, const char *command)
Definition: main/cli.c:183
const int fd
Definition: cli.h:159
int inuse
Definition: cli.h:179
const char * usage
Definition: cli.h:177
const char * args

References a, allowed_on_shutdown(), args, ast_atomic_fetchadd_int(), ast_cli(), ast_free, ast_join, AST_MAX_ARGS, ast_module_running_ref, ast_module_unref, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_shutting_down(), CLI_FAILURE, CLI_HANDLER, cli_has_permissions(), CLI_SHOWUSAGE, CLI_SUCCESS, done, ast_cli_args::fd, find_best(), find_cli(), ast_cli_entry::handler, ast_cli_entry::inuse, ast_cli_entry::module, NULL, parse_args(), RESULT_FAILURE, RESULT_SUCCESS, S_OR, and ast_cli_entry::usage.

Referenced by ast_cli_command_multiple_full().

◆ ast_cli_command_multiple_full()

int ast_cli_command_multiple_full ( int  uid,
int  gid,
int  fd,
size_t  size,
const char *  s 
)

Executes multiple CLI commands Interpret strings separated by NULL and execute each one, sending output to fd if uid has permissions, uid = CLI_NO_PERMS to avoid checking users permissions. gid = CLI_NO_PERMS to avoid checking group permissions.

Parameters
uidUser ID that is trying to run the command.
gidGroup ID that is trying to run the command.
fdpipe
sizeis the total size of the string
sincoming string
Returns
number of commands executed

Definition at line 3015 of file main/cli.c.

3016{
3017 char cmd[512];
3018 int x, y = 0, count = 0;
3019
3020 for (x = 0; x < size; x++) {
3021 cmd[y] = s[x];
3022 y++;
3023 if (s[x] == '\0') {
3024 ast_cli_command_full(uid, gid, fd, cmd);
3025 y = 0;
3026 count++;
3027 }
3028 }
3029 return count;
3030}
int ast_cli_command_full(int uid, int gid, int fd, const char *s)
Interprets a command Interpret a command s, sending output to fd if uid:gid has permissions to run th...
Definition: main/cli.c:2950

References ast_cli_command_full(), and ast_cli_args::fd.

Referenced by netconsole().

◆ ast_cli_complete()

char * ast_cli_complete ( const char *  word,
const char *const  choices[],
int  pos 
)

Helper function to generate cli entries from a NULL-terminated array. Returns the n-th matching entry from the array, or NULL if not found. Can be used to implement generate() for static entries as below (in this example we complete the word in position 2):

char *my_generate(const char *line, const char *word, int pos, int n)
{
static const char * const choices[] = { "one", "two", "three", NULL };
if (pos == 2)
return ast_cli_complete(word, choices, n);
else
return NULL;
}
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: main/cli.c:1823

Definition at line 1823 of file main/cli.c.

1824{
1825 int i, which = 0, len;
1826 len = ast_strlen_zero(word) ? 0 : strlen(word);
1827
1828 for (i = 0; choices[i]; i++) {
1829 if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state) {
1830 if (state != -1) {
1831 return ast_strdup(choices[i]);
1832 }
1833
1834 if (ast_cli_completion_add(ast_strdup(choices[i]))) {
1835 return NULL;
1836 }
1837 }
1838 }
1839 return NULL;
1840}
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2737

References ast_cli_completion_add(), ast_strdup, ast_strlen_zero(), len(), and NULL.

Referenced by cli_odbc_read(), cli_odbc_write(), handle_bridge_kick_channel(), handle_cli_core_show_translation(), handle_cli_devstate_change(), handle_cli_iax2_prune_realtime(), handle_cli_presencestate_change(), handle_core_set_debug_channel(), handle_orig(), handle_refresh(), handle_showcalls(), handle_softhangup(), pjsip_set_logger(), and sorcery_memory_cache_stale().

◆ ast_cli_completion_add()

int ast_cli_completion_add ( char *  value)

Add a result to a request for completion options.

Parameters
valueA completion option text.
Return values
0Success
-1Failure

This is an alternative to returning individual values from CLI_GENERATE. Instead of repeatedly being asked for the next match and having to start over, you can call this function repeatedly from your own stateful loop. When all matches have been added you can return NULL from the CLI_GENERATE function.

Note
This function always eventually results in calling ast_free on value.

Definition at line 2737 of file main/cli.c.

2738{
2739 return cli_completion_vector_add(ast_threadstorage_get_ptr(&completion_storage), value);
2740}
static int cli_completion_vector_add(struct ast_vector_string *vec, char *value)
Definition: main/cli.c:2716
int value
Definition: syslog.c:37
void * ast_threadstorage_get_ptr(struct ast_threadstorage *ts)
Retrieve a raw pointer from threadstorage.

References ast_threadstorage_get_ptr(), cli_completion_vector_add(), and value.

Referenced by aeap_tab_complete_name(), ari_set_debug(), ast_cli_complete(), ast_complete_applications(), ast_complete_channels(), category_complete(), cli_complete_endpoint(), cli_complete_show(), cli_complete_uri(), complete_app(), complete_bridge_live_search(), complete_bridge_participant(), complete_bridge_technology(), complete_channeltypes(), complete_config_module(), complete_config_option(), complete_config_type(), complete_core_id(), complete_country(), complete_indications(), complete_session(), complete_show_sorcery_object(), complete_sorcery_object(), complete_trans_path_choice(), config_object_tab_complete_name(), handle_cli_config_reload(), handle_cli_sound_show(), handle_debug_category(), handle_manager_show_event(), handle_show_named_acl_cmd(), handle_showmanager(), handle_showmancmd(), module_load_helper_on_file(), topic_complete_name(), and tps_taskprocessor_tab_complete().

◆ ast_cli_completion_matches()

char ** ast_cli_completion_matches ( const char *  text,
const char *  word 
)

Generates a NULL-terminated array of strings that 1) begin with the string in the second parameter, and 2) are valid in a command after the string in the first parameter.

The first entry (offset 0) of the result is the longest common substring in the results, useful to extend the string that has been completed. Subsequent entries are all possible values, followed by a NULL. All strings and the array itself are malloc'ed and must be freed by the caller.

Warning
This function cannot be called recursively so it will always fail if called from a CLI_GENERATE callback.

Definition at line 2681 of file main/cli.c.

2682{
2684 char **match_list;
2685
2686 if (!vec) {
2687 return NULL;
2688 }
2689
2690 if (AST_VECTOR_APPEND(vec, NULL)) {
2691 /* We failed to NULL terminate the elements */
2694
2695 return NULL;
2696 }
2697
2698 match_list = AST_VECTOR_STEAL_ELEMENTS(vec);
2700
2701 return match_list;
2702}
struct ast_vector_string * ast_cli_completion_vector(const char *text, const char *word)
Generates a vector of strings for CLI completion.
Definition: main/cli.c:2742
String vector definitions.
Definition: vector.h:55
#define AST_VECTOR_STEAL_ELEMENTS(vec)
Steal the elements from a vector and reinitialize.
Definition: vector.h:151
#define AST_VECTOR_PTR_FREE(vec)
Deallocates this vector pointer.
Definition: vector.h:200
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:873

References ast_cli_completion_vector(), ast_free, AST_VECTOR_APPEND, AST_VECTOR_CALLBACK_VOID, AST_VECTOR_PTR_FREE, AST_VECTOR_STEAL_ELEMENTS, NULL, and text.

Referenced by handle_commandmatchesarray().

◆ ast_cli_completion_vector()

struct ast_vector_string * ast_cli_completion_vector ( const char *  text,
const char *  word 
)

Generates a vector of strings for CLI completion.

Parameters
textComplete input being matched.
wordCurrent word being matched

The results contain strings that both: 1) Begin with the string in word. 2) Are valid in a command after the string in text.

The first entry (offset 0) of the result is the longest common substring in the results, useful to extend the string that has been completed. Subsequent entries are all possible values.

Note
All strings and the vector itself are malloc'ed and must be freed by the caller.
The vector is sorted and does not contain any duplicates.
Warning
This function cannot be called recursively so it will always fail if called from a CLI_GENERATE callback.

Definition at line 2742 of file main/cli.c.

2743{
2744 char *retstr, *prevstr;
2745 size_t max_equal;
2746 size_t which = 0;
2747 struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec));
2748
2749 /* Recursion into this function is a coding error. */
2750 ast_assert(!ast_threadstorage_get_ptr(&completion_storage));
2751
2752 if (!vec) {
2753 return NULL;
2754 }
2755
2756 if (ast_threadstorage_set_ptr(&completion_storage, vec)) {
2757 ast_log(LOG_ERROR, "Failed to initialize threadstorage for completion.\n");
2758 ast_free(vec);
2759
2760 return NULL;
2761 }
2762
2763 while ((retstr = ast_cli_generator(text, word, which)) != NULL) {
2764 if (cli_completion_vector_add(vec, retstr)) {
2765 ast_threadstorage_set_ptr(&completion_storage, NULL);
2766
2767 goto vector_cleanup;
2768 }
2769
2770 ++which;
2771 }
2772
2773 ast_threadstorage_set_ptr(&completion_storage, NULL);
2774
2775 if (!AST_VECTOR_SIZE(vec)) {
2777
2778 return NULL;
2779 }
2780
2781 prevstr = AST_VECTOR_GET(vec, 0);
2782 max_equal = strlen(prevstr);
2783 which = 1;
2784
2785 /* Find the longest substring that is common to all results
2786 * (it is a candidate for completion), and store a copy in entry 0.
2787 */
2788 while (which < AST_VECTOR_SIZE(vec)) {
2789 size_t i = 0;
2790
2791 retstr = AST_VECTOR_GET(vec, which);
2792 /* Check for and remove duplicate strings. */
2793 if (!strcasecmp(prevstr, retstr)) {
2794 AST_VECTOR_REMOVE(vec, which, 1);
2795 ast_free(retstr);
2796
2797 continue;
2798 }
2799
2800 while (i < max_equal && toupper(prevstr[i]) == toupper(retstr[i])) {
2801 i++;
2802 }
2803
2804 max_equal = i;
2805 prevstr = retstr;
2806 ++which;
2807 }
2808
2809 /* Insert longest match to position 0. */
2810 retstr = ast_strndup(AST_VECTOR_GET(vec, 0), max_equal);
2811 if (!retstr || AST_VECTOR_INSERT_AT(vec, 0, retstr)) {
2812 ast_free(retstr);
2813
2814 goto vector_cleanup;
2815 }
2816
2817 return vec;
2818
2819vector_cleanup:
2822
2823 return NULL;
2824}
#define ast_strndup(str, len)
A wrapper for strndup()
Definition: astmm.h:256
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define LOG_ERROR
char * ast_cli_generator(const char *text, const char *word, int state)
Readline madness Useful for readline, that's about it.
Definition: main/cli.c:2928
int ast_threadstorage_set_ptr(struct ast_threadstorage *ts, void *ptr)
Set a raw pointer from threadstorage.
#define ast_assert(a)
Definition: utils.h:776
#define AST_VECTOR_INSERT_AT(vec, idx, elem)
Insert an element at a specific position in a vector, growing the vector if needed.
Definition: vector.h:349
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
Definition: vector.h:423

References ast_assert, ast_calloc, ast_cli_generator(), ast_free, ast_log, ast_strndup, ast_threadstorage_get_ptr(), ast_threadstorage_set_ptr(), AST_VECTOR_CALLBACK_VOID, AST_VECTOR_GET, AST_VECTOR_INSERT_AT, AST_VECTOR_PTR_FREE, AST_VECTOR_REMOVE, AST_VECTOR_SIZE, cli_completion_vector_add(), LOG_ERROR, NULL, and text.

Referenced by ast_cli_completion_matches(), AST_TEST_DEFINE(), and cli_complete().

◆ ast_cli_generator()

char * ast_cli_generator ( const char *  text,
const char *  word,
int  state 
)

Readline madness Useful for readline, that's about it.

Return values
0on success
-1on failure

Only call this function to proxy the CLI generator to another.

Definition at line 2928 of file main/cli.c.

2929{
2930 return __ast_cli_generator(text, word, state, 1);
2931}
static char * __ast_cli_generator(const char *text, const char *word, int state, int lock)
Definition: main/cli.c:2840

References __ast_cli_generator(), and text.

Referenced by ast_cli_completion_vector(), cli_alias_passthrough(), and handle_cli_check_permissions().

◆ ast_cli_perms_init()

int ast_cli_perms_init ( int  reload)

Provided by cli.c

Definition at line 2081 of file main/cli.c.

2082{
2083 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2084 struct ast_config *cfg;
2085 char *cat = NULL;
2086 struct ast_variable *v;
2087 struct usergroup_cli_perm *user_group, *cp_entry;
2088 struct cli_perm *perm = NULL;
2089 struct passwd *pw;
2090 struct group *gr;
2091
2093 ast_log(LOG_NOTICE, "You must wait until last 'cli reload permissions' command finish\n");
2094 return 1;
2095 }
2096
2097 cfg = ast_config_load2(perms_config, "" /* core, can't reload */, config_flags);
2098 if (!cfg) {
2100 return 1;
2101 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2103 return 0;
2104 }
2105
2106 /* free current structures. */
2108
2109 while ((cat = ast_category_browse(cfg, cat))) {
2110 if (!strcasecmp(cat, "general")) {
2111 /* General options */
2112 for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
2113 if (!strcasecmp(v->name, "default_perm")) {
2114 cli_default_perm = (!strcasecmp(v->value, "permit")) ? 1: 0;
2115 }
2116 }
2117 continue;
2118 }
2119
2120 /* users or groups */
2121 gr = NULL, pw = NULL;
2122 if (cat[0] == '@') {
2123 /* This is a group */
2124 gr = getgrnam(&cat[1]);
2125 if (!gr) {
2126 ast_log (LOG_WARNING, "Unknown group '%s'\n", &cat[1]);
2127 continue;
2128 }
2129 } else {
2130 /* This is a user */
2131 pw = getpwnam(cat);
2132 if (!pw) {
2133 ast_log (LOG_WARNING, "Unknown user '%s'\n", cat);
2134 continue;
2135 }
2136 }
2137 user_group = NULL;
2138 /* Check for duplicates */
2140 AST_LIST_TRAVERSE(&cli_perms, cp_entry, list) {
2141 if ((pw && cp_entry->uid == pw->pw_uid) || (gr && cp_entry->gid == gr->gr_gid)) {
2142 /* if it is duplicated, just added this new settings, to
2143 the current list. */
2144 user_group = cp_entry;
2145 break;
2146 }
2147 }
2149
2150 if (!user_group) {
2151 /* alloc space for the new user config. */
2152 user_group = ast_calloc(1, sizeof(*user_group));
2153 if (!user_group) {
2154 continue;
2155 }
2156 user_group->uid = (pw ? pw->pw_uid : -1);
2157 user_group->gid = (gr ? gr->gr_gid : -1);
2158 user_group->perms = ast_calloc(1, sizeof(*user_group->perms));
2159 if (!user_group->perms) {
2160 ast_free(user_group);
2161 continue;
2162 }
2163 }
2164 for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
2165 if (ast_strlen_zero(v->value)) {
2166 /* we need to check this condition cause it could break security. */
2167 ast_log(LOG_WARNING, "Empty permit/deny option in user '%s'\n", cat);
2168 continue;
2169 }
2170 if (!strcasecmp(v->name, "permit")) {
2171 perm = ast_calloc(1, sizeof(*perm));
2172 if (perm) {
2173 perm->permit = 1;
2174 perm->command = ast_strdup(v->value);
2175 }
2176 } else if (!strcasecmp(v->name, "deny")) {
2177 perm = ast_calloc(1, sizeof(*perm));
2178 if (perm) {
2179 perm->permit = 0;
2180 perm->command = ast_strdup(v->value);
2181 }
2182 } else {
2183 /* up to now, only 'permit' and 'deny' are possible values. */
2184 ast_log(LOG_WARNING, "Unknown '%s' option\n", v->name);
2185 continue;
2186 }
2187 if (perm) {
2188 /* Added the permission to the user's list. */
2189 AST_LIST_INSERT_TAIL(user_group->perms, perm, list);
2190 perm = NULL;
2191 }
2192 }
2194 AST_RWLIST_INSERT_TAIL(&cli_perms, user_group, list);
2196 }
2197
2198 ast_config_destroy(cfg);
2200 return 0;
2201}
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3541
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
#define CONFIG_STATUS_FILEUNCHANGED
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
@ CONFIG_FLAG_FILEUNCHANGED
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
#define LOG_NOTICE
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define ast_mutex_unlock(a)
Definition: lock.h:197
#define ast_mutex_trylock(a)
Definition: lock.h:198
static ast_mutex_t permsconfiglock
mutex used to prevent a user from running the 'cli reload permissions' command while it is already ru...
Definition: main/cli.c:91
static int cli_default_perm
Default permissions value 1=Permit 0=Deny.
Definition: main/cli.c:87
static void destroy_user_perms(void)
cleanup (free) cli_perms linkedlist.
Definition: main/cli.c:2065
static const char perms_config[]
CLI permissions config file.
Definition: main/cli.c:85
static int reload(void)
Structure used to handle boolean flags.
Definition: utils.h:217
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
List of restrictions per user.
Definition: main/cli.c:69
unsigned int permit
Definition: main/cli.c:70
char * command
Definition: main/cli.c:71
List of users and permissions.
Definition: main/cli.c:93
list of users to apply restrictions.
Definition: main/cli.c:78
struct cli_perm_head * perms
Definition: main/cli.c:81

References ast_calloc, ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_free, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log, ast_mutex_trylock, ast_mutex_unlock, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_strdup, ast_strlen_zero(), ast_variable_browse(), cli_default_perm, cli_perm::command, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, destroy_user_perms(), usergroup_cli_perm::gid, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, cli_perm::permit, usergroup_cli_perm::perms, perms_config, permsconfiglock, reload(), usergroup_cli_perm::uid, and ast_variable::value.

Referenced by asterisk_daemon(), and handle_cli_reload_permissions().

◆ ast_cli_print_timestr_fromseconds()

void ast_cli_print_timestr_fromseconds ( int  fd,
int  seconds,
const char *  prefix 
)

Print on cli a duration in seconds in format s year(s), s week(s), s day(s), s hour(s), s second(s)

Since
13.8
Parameters
fdfd to print by ast_cli
secondsThe time (in seconds) to print
prefixA Prefix string to add before of duration formatted

Definition at line 3032 of file main/cli.c.

3033{
3034 print_uptimestr(fd, ast_tv(seconds, 0), prefix, 0);
3035}
static char prefix[MAX_PREFIX]
Definition: http.c:144
static void print_uptimestr(int fd, struct timeval timeval, const char *prefix, int printsec)
Definition: main/cli.c:913
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235

References ast_tv(), ast_cli_args::fd, prefix, and print_uptimestr().

Referenced by handle_cdr_pgsql_status(), handle_cli_realtime_pgsql_status(), and realtime_ldap_status().

◆ ast_cli_unregister()

int ast_cli_unregister ( struct ast_cli_entry e)

Unregisters a command or an array of commands.

Parameters
ewhich cli entry to unregister Unregister your own command. You must pass a completed ast_cli_entry structure
Returns
0

Definition at line 2408 of file main/cli.c.

2409{
2410 if (e->inuse) {
2411 ast_log(LOG_WARNING, "Can't remove command that is in use\n");
2412 } else {
2414 AST_RWLIST_REMOVE(&helpers, e, list);
2417 ast_free(e->_full_cmd);
2418 e->_full_cmd = NULL;
2419 if (e->handler) {
2420 /* this is a new-style entry. Reset fields and free memory. */
2421 char *cmda = (char *) e->cmda;
2422 memset(cmda, '\0', sizeof(e->cmda));
2423 ast_free(e->command);
2424 e->command = NULL;
2425 e->usage = NULL;
2426 }
2427 }
2428 return 0;
2429}
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:885
static void remove_shutdown_command(struct ast_cli_entry *e)
Definition: main/cli.c:2401

References ast_cli_entry::_full_cmd, ast_free, ast_log, AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_cli_entry::cmda, ast_cli_entry::command, ast_cli_entry::handler, ast_cli_entry::inuse, ast_cli_entry::list, LOG_WARNING, NULL, remove_shutdown_command(), and ast_cli_entry::usage.

Referenced by aco_deinit(), alias_unregister_cb(), ast_cli_unregister_multiple(), unload_module(), and xmldoc_unload_documentation().

◆ ast_cli_unregister_multiple()

int ast_cli_unregister_multiple ( struct ast_cli_entry e,
int  len 
)

Unregister multiple commands.

Parameters
epointer to first cli entry to unregister
lennumber of entries to unregister

Definition at line 2519 of file main/cli.c.

2520{
2521 int i, res = 0;
2522
2523 for (i = 0; i < len; i++)
2524 res |= ast_cli_unregister(e + i);
2525
2526 return res;
2527}
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
Definition: main/cli.c:2408

References ast_cli_unregister(), and len().

Referenced by cli_channels_shutdown(), and cli_shutdown().

◆ ast_complete_channels()

char * ast_complete_channels ( const char *  line,
const char *  word,
int  pos,
int  state,
int  rpos 
)

Command completion for the list of active channels.

This can be called from a CLI command completion function that wants to complete from the list of active channels. 'rpos' is the required position in the command. This function will return NULL immediately if 'rpos' is not the same as the current position, 'pos'.

Definition at line 1842 of file main/cli.c.

1843{
1844 int wordlen = strlen(word), which = 0;
1845 struct ao2_container *cached_channels;
1846 char *ret = NULL;
1847 struct ao2_iterator iter;
1848 struct ast_channel_snapshot *snapshot;
1849
1850 if (pos != rpos) {
1851 return NULL;
1852 }
1853
1854 cached_channels = ast_channel_cache_all();
1855
1856 iter = ao2_iterator_init(cached_channels, 0);
1857 for (; (snapshot = ao2_iterator_next(&iter)); ao2_ref(snapshot, -1)) {
1858 if (!strncasecmp(word, snapshot->base->name, wordlen) && (++which > state)) {
1859 if (state != -1) {
1860 ret = ast_strdup(snapshot->base->name);
1861 ao2_ref(snapshot, -1);
1862 break;
1863 }
1864
1865 if (ast_cli_completion_add(ast_strdup(snapshot->base->name))) {
1866 ao2_ref(snapshot, -1);
1867 break;
1868 }
1869 }
1870 }
1871 ao2_iterator_destroy(&iter);
1872 ao2_ref(cached_channels, -1);
1873
1874 return ret;
1875}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
enum cc_state state
Definition: ccss.c:399
struct ao2_container * ast_channel_cache_all(void)
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
const ast_string_field name
Structure representing a snapshot of channel state.
struct ast_channel_snapshot_base * base

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_channel_cache_all(), ast_cli_completion_add(), ast_strdup, ast_channel_snapshot::base, ast_channel_snapshot_base::name, NULL, and state.

Referenced by cli_complete_notify(), handle_cli_agi_add_cmd(), handle_cli_mixmonitor(), handle_core_set_debug_channel(), handle_dump_frames(), handle_redirect(), handle_remb_set(), handle_set_chanvar(), handle_show_chanvar(), handle_show_hangup_channel(), handle_showchan(), and handle_softhangup().

◆ ast_debug_get_by_module()

unsigned int ast_debug_get_by_module ( const char *  module)

Get the debug level for a module.

Parameters
modulethe name of module
Returns
the debug level

Definition at line 136 of file main/cli.c.

137{
138 struct module_level *ml;
139 unsigned int res = 0;
140
142 AST_LIST_TRAVERSE(&debug_modules, ml, entry) {
143 if (!strcasecmp(ml->module, module)) {
144 res = ml->level;
145 break;
146 }
147 }
149
150 return res;
151}
static struct module_level_list debug_modules
Definition: main/cli.c:107
map a debug or verbose level to a module name
Definition: main/cli.c:98
unsigned int level
Definition: main/cli.c:99

References AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, debug_modules, and module_level::level.

◆ AST_THREADSTORAGE_RAW()

AST_THREADSTORAGE_RAW ( completion_storage  )

◆ channel_set_debug()

static int channel_set_debug ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 1487 of file main/cli.c.

1488{
1489 struct ast_channel *chan = obj;
1490 struct channel_set_debug_args *args = data;
1491
1492 ast_channel_lock(chan);
1493
1494 if (!(ast_channel_fin(chan) & DEBUGCHAN_FLAG) || !(ast_channel_fout(chan) & DEBUGCHAN_FLAG)) {
1495 if (args->is_off) {
1498 } else {
1501 }
1502 ast_cli(args->fd, "Debugging %s on channel %s\n", args->is_off ? "disabled" : "enabled",
1503 ast_channel_name(chan));
1504 }
1505
1506 ast_channel_unlock(chan);
1507
1508 return 0;
1509}
const char * ast_channel_name(const struct ast_channel *chan)
#define DEBUGCHAN_FLAG
Definition: channel.h:877
unsigned int ast_channel_fin(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2972
void ast_channel_fin_set(struct ast_channel *chan, unsigned int value)
unsigned int ast_channel_fout(const struct ast_channel *chan)
void ast_channel_fout_set(struct ast_channel *chan, unsigned int value)
#define ast_channel_unlock(chan)
Definition: channel.h:2973
Main Channel structure associated with a channel.

References args, ast_channel_fin(), ast_channel_fin_set(), ast_channel_fout(), ast_channel_fout_set(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_cli(), and DEBUGCHAN_FLAG.

Referenced by handle_core_set_debug_channel().

◆ cli_channels_shutdown()

static void cli_channels_shutdown ( void  )
static

Definition at line 2208 of file main/cli.c.

2209{
2211}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: main/cli.c:2519

References ARRAY_LEN, ast_cli_unregister_multiple(), and cli_channels_cli.

Referenced by ast_cli_channels_init().

◆ cli_completion_vector_add()

static int cli_completion_vector_add ( struct ast_vector_string vec,
char *  value 
)
static

Definition at line 2716 of file main/cli.c.

2717{
2718 if (!value) {
2719 return 0;
2720 }
2721
2722 if (!vec || AST_VECTOR_ADD_SORTED(vec, value, strcasecmp)) {
2723 if (vec) {
2724 ast_threadstorage_set_ptr(&completion_storage, NULL);
2725
2727 AST_VECTOR_FREE(vec);
2728 }
2729 ast_free(value);
2730
2731 return -1;
2732 }
2733
2734 return 0;
2735}
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:185
#define AST_VECTOR_ADD_SORTED(vec, elem, cmp)
Add an element into a sorted vector.
Definition: vector.h:382

References ast_free, ast_threadstorage_set_ptr(), AST_VECTOR_ADD_SORTED, AST_VECTOR_CALLBACK_VOID, AST_VECTOR_FREE, NULL, and value.

Referenced by ast_cli_completion_add(), and ast_cli_completion_vector().

◆ cli_has_permissions()

static int cli_has_permissions ( int  uid,
int  gid,
const char *  command 
)
static

Definition at line 183 of file main/cli.c.

184{
185 struct usergroup_cli_perm *user_perm;
186 struct cli_perm *perm;
187 /* set to the default permissions general option. */
188 int isallowg = cli_default_perm, isallowu = -1, ispattern;
189 regex_t regexbuf;
190
191 /* if uid == -1 or gid == -1 do not check permissions.
192 if uid == -2 and gid == -2 is because rasterisk client didn't send
193 the credentials, so the cli_default_perm will be applied. */
194 if ((uid == CLI_NO_PERMS && gid == CLI_NO_PERMS) || command[0] == '_') {
195 return 1;
196 }
197
198 if (gid < 0 && uid < 0) {
199 return cli_default_perm;
200 }
201
203 AST_LIST_TRAVERSE(&cli_perms, user_perm, list) {
204 if (user_perm->gid != gid && user_perm->uid != uid) {
205 continue;
206 }
207 AST_LIST_TRAVERSE(user_perm->perms, perm, list) {
208 if (strcasecmp(perm->command, "all") && strncasecmp(perm->command, command, strlen(perm->command))) {
209 /* if the perm->command is a pattern, check it against command. */
210 ispattern = !regcomp(&regexbuf, perm->command, REG_EXTENDED | REG_NOSUB | REG_ICASE);
211 if (ispattern && regexec(&regexbuf, command, 0, NULL, 0)) {
212 regfree(&regexbuf);
213 continue;
214 }
215 if (!ispattern) {
216 continue;
217 }
218 regfree(&regexbuf);
219 }
220 if (user_perm->uid == uid) {
221 /* this is a user definition. */
222 isallowu = perm->permit;
223 } else {
224 /* otherwise is a group definition. */
225 isallowg = perm->permit;
226 }
227 }
228 }
230 if (isallowu > -1) {
231 /* user definition override group definition. */
232 isallowg = isallowu;
233 }
234
235 return isallowg;
236}
#define CLI_NO_PERMS
Definition: cli.h:38
struct cli_perm::@338 list

References AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, cli_default_perm, CLI_NO_PERMS, cli_perm::command, usergroup_cli_perm::gid, cli_perm::list, NULL, cli_perm::permit, usergroup_cli_perm::perms, and usergroup_cli_perm::uid.

Referenced by ast_cli_command_full(), and handle_cli_check_permissions().

◆ cli_is_registered()

static int cli_is_registered ( struct ast_cli_entry e)
static

Definition at line 2389 of file main/cli.c.

2390{
2391 struct ast_cli_entry *cur = NULL;
2392
2393 while ((cur = cli_next(cur))) {
2394 if (cur == e) {
2395 return 1;
2396 }
2397 }
2398 return 0;
2399}

References cli_next(), and NULL.

Referenced by __ast_cli_register().

◆ cli_next()

static struct ast_cli_entry * cli_next ( struct ast_cli_entry e)
static

Definition at line 966 of file main/cli.c.

967{
968 if (e) {
969 return AST_LIST_NEXT(e, list);
970 } else {
971 return AST_LIST_FIRST(&helpers);
972 }
973}
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439

References AST_LIST_FIRST, AST_LIST_NEXT, and ast_cli_entry::list.

Referenced by __ast_cli_generator(), cli_is_registered(), find_cli(), handle_cli_check_permissions(), and help1().

◆ cli_shutdown()

static void cli_shutdown ( void  )
static

Definition at line 2203 of file main/cli.c.

References ARRAY_LEN, ast_cli_unregister_multiple(), and cli_cli.

Referenced by ast_builtins_init().

◆ complete_number()

static char * complete_number ( const char *  partial,
unsigned int  min,
unsigned int  max,
int  n 
)
static

Definition at line 363 of file main/cli.c.

364{
365 int i, count = 0;
366 unsigned int prospective[2];
367 unsigned int part = strtoul(partial, NULL, 10);
368 char next[13];
369
370 if (part < min || part > max) {
371 return NULL;
372 }
373
374 for (i = 0; i < 21; i++) {
375 if (i == 0) {
376 prospective[0] = prospective[1] = part;
377 } else if (part == 0 && !ast_strlen_zero(partial)) {
378 break;
379 } else if (i < 11) {
380 prospective[0] = prospective[1] = part * 10 + (i - 1);
381 } else {
382 prospective[0] = (part * 10 + (i - 11)) * 10;
383 prospective[1] = prospective[0] + 9;
384 }
385 if (i < 11 && (prospective[0] < min || prospective[0] > max)) {
386 continue;
387 } else if (prospective[1] < min || prospective[0] > max) {
388 continue;
389 }
390
391 if (++count > n) {
392 if (i < 11) {
393 snprintf(next, sizeof(next), "%u", prospective[0]);
394 } else {
395 snprintf(next, sizeof(next), "%u...", prospective[0] / 10);
396 }
397 return ast_strdup(next);
398 }
399 }
400 return NULL;
401}
#define min(a, b)
Definition: f2c.h:197
size_t max
Definition: main/cli.c:113

References ast_strdup, ast_strlen_zero(), max, min, and NULL.

Referenced by handle_debug(), handle_trace(), and handle_verbose().

◆ destroy_user_perms()

static void destroy_user_perms ( void  )
static

cleanup (free) cli_perms linkedlist.

Definition at line 2065 of file main/cli.c.

2066{
2067 struct cli_perm *perm;
2068 struct usergroup_cli_perm *user_perm;
2069
2071 while ((user_perm = AST_LIST_REMOVE_HEAD(&cli_perms, list))) {
2072 while ((perm = AST_LIST_REMOVE_HEAD(user_perm->perms, list))) {
2073 ast_free(perm->command);
2074 ast_free(perm);
2075 }
2076 ast_free(user_perm);
2077 }
2079}
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
struct usergroup_cli_perm::@339 list

References ast_free, AST_LIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, cli_perm::command, usergroup_cli_perm::list, and usergroup_cli_perm::perms.

Referenced by ast_cli_perms_init().

◆ find_best()

static char * find_best ( const char *  argv[])
static

Definition at line 2371 of file main/cli.c.

2372{
2373 static char cmdline[80];
2374 int x;
2375 /* See how close we get, then print the candidate */
2376 const char *myargv[AST_MAX_CMD_LEN] = { NULL, };
2377
2379 for (x = 0; argv[x]; x++) {
2380 myargv[x] = argv[x];
2381 if (!find_cli(myargv, -1))
2382 break;
2383 }
2385 ast_join(cmdline, sizeof(cmdline), myargv);
2386 return cmdline;
2387}

References ast_join, AST_MAX_CMD_LEN, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, find_cli(), and NULL.

Referenced by ast_cli_command_full().

◆ find_cli()

static struct ast_cli_entry * find_cli ( const char *const  cmds[],
int  match_type 
)
static

Definition at line 2327 of file main/cli.c.

2328{
2329 int matchlen = -1; /* length of longest match so far */
2330 struct ast_cli_entry *cand = NULL, *e=NULL;
2331
2332 while ( (e = cli_next(e)) ) {
2333 /* word-by word regexp comparison */
2334 const char * const *src = cmds;
2335 const char * const *dst = e->cmda;
2336 int n = 0;
2337 for (;; dst++, src += n) {
2338 n = word_match(*src, *dst);
2339 if (n < 0)
2340 break;
2341 }
2342 if (ast_strlen_zero(*dst) || ((*dst)[0] == '[' && ast_strlen_zero(dst[1]))) {
2343 /* no more words in 'e' */
2344 if (ast_strlen_zero(*src)) /* exact match, cannot do better */
2345 break;
2346 /* Here, cmds has more words than the entry 'e' */
2347 if (match_type != 0) /* but we look for almost exact match... */
2348 continue; /* so we skip this one. */
2349 /* otherwise we like it (case 0) */
2350 } else { /* still words in 'e' */
2351 if (ast_strlen_zero(*src))
2352 continue; /* cmds is shorter than 'e', not good */
2353 /* Here we have leftover words in cmds and 'e',
2354 * but there is a mismatch. We only accept this one if match_type == -1
2355 * and this is the last word for both.
2356 */
2357 if (match_type != -1 || !ast_strlen_zero(src[1]) ||
2358 !ast_strlen_zero(dst[1])) /* not the one we look for */
2359 continue;
2360 /* good, we are in case match_type == -1 and mismatch on last word */
2361 }
2362 if (src - cmds > matchlen) { /* remember the candidate */
2363 matchlen = src - cmds;
2364 cand = e;
2365 }
2366 }
2367
2368 return e ? e : cand;
2369}

References ast_strlen_zero(), cli_next(), NULL, and word_match().

Referenced by __ast_cli_register(), ast_cli_command_full(), find_best(), and handle_help().

◆ find_module_level()

static struct module_level * find_module_level ( const char *  module,
struct module_level_list mll 
)
static

Find the module level setting.

Parameters
moduleModule name to look for.
mllList to search.
Return values
levelstruct found on success.
NULLnot found.

Definition at line 351 of file main/cli.c.

352{
353 struct module_level *ml;
354
355 AST_LIST_TRAVERSE(mll, ml, entry) {
356 if (!strcasecmp(ml->module, module))
357 return ml;
358 }
359
360 return NULL;
361}

References AST_LIST_TRAVERSE, and NULL.

Referenced by handle_debug_or_trace().

◆ group_show_channels()

static char * group_show_channels ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1877 of file main/cli.c.

1878{
1879#define FORMAT_STRING "%-25s %-20s %-20s\n"
1880
1881 struct ast_group_info *gi = NULL;
1882 int numchans = 0;
1883 regex_t regexbuf;
1884 int havepattern = 0;
1885
1886 switch (cmd) {
1887 case CLI_INIT:
1888 e->command = "group show channels";
1889 e->usage =
1890 "Usage: group show channels [pattern]\n"
1891 " Lists all currently active channels with channel group(s) specified.\n"
1892 " Optional regular expression pattern is matched to group names for each\n"
1893 " channel.\n";
1894 return NULL;
1895 case CLI_GENERATE:
1896 return NULL;
1897 }
1898
1899 if (a->argc < 3 || a->argc > 4)
1900 return CLI_SHOWUSAGE;
1901
1902 if (a->argc == 4) {
1903 if (regcomp(&regexbuf, a->argv[3], REG_EXTENDED | REG_NOSUB))
1904 return CLI_SHOWUSAGE;
1905 havepattern = 1;
1906 }
1907
1908 ast_cli(a->fd, FORMAT_STRING, "Channel", "Group", "Category");
1909
1911
1913 while (gi) {
1914 if (!havepattern || !regexec(&regexbuf, gi->group, 0, NULL, 0)) {
1915 ast_cli(a->fd, FORMAT_STRING, ast_channel_name(gi->chan), gi->group, (ast_strlen_zero(gi->category) ? "(default)" : gi->category));
1916 numchans++;
1917 }
1918 gi = AST_LIST_NEXT(gi, group_list);
1919 }
1920
1922
1923 if (havepattern)
1924 regfree(&regexbuf);
1925
1926 ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
1927 return CLI_SUCCESS;
1928#undef FORMAT_STRING
1929}
#define ESS(x)
Definition: cli.h:59
int ast_app_group_list_unlock(void)
Unlock the group count list.
Definition: main/app.c:2351
struct ast_group_info * ast_app_group_list_head(void)
Get the head of the group count list.
Definition: main/app.c:2346
int ast_app_group_list_rdlock(void)
Read Lock the group count list.
Definition: main/app.c:2341
#define FORMAT_STRING
channel group info
Definition: channel.h:2965
struct ast_group_info::@215 group_list
char * category
Definition: channel.h:2967
char * group
Definition: channel.h:2968
struct ast_channel * chan
Definition: channel.h:2966

References a, ast_app_group_list_head(), ast_app_group_list_rdlock(), ast_app_group_list_unlock(), ast_channel_name(), ast_cli(), AST_LIST_NEXT, ast_strlen_zero(), ast_group_info::category, ast_group_info::chan, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ESS, FORMAT_STRING, ast_group_info::group, ast_group_info::group_list, NULL, and ast_cli_entry::usage.

◆ handle_chanlist()

static char * handle_chanlist ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1104 of file main/cli.c.

1105{
1106#define FORMAT_STRING "%-64.64s %-32.32s %-7.7s %-30.30s\n"
1107#define FORMAT_STRING2 "%-64.64s %-32.32s %-7.7s %-30.30s\n"
1108#define CONCISE_FORMAT_STRING "%s!%s!%s!%d!%s!%s!%s!%s!%s!%s!%d!%s!%s!%s\n"
1109#define VERBOSE_FORMAT_STRING "%-80.80s %-24.24s %-24.24s %4d %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-11.11s %-20.20s\n"
1110#define VERBOSE_FORMAT_STRING2 "%-80.80s %-24.24s %-24.24s %-4.4s %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-11.11s %-20.20s\n"
1111
1112 struct ao2_container *channels;
1113 struct ao2_iterator it_chans;
1114 struct ast_channel_snapshot *cs;
1115 int numchans = 0, concise = 0, verbose = 0, count = 0;
1116
1117 switch (cmd) {
1118 case CLI_INIT:
1119 e->command = "core show channels [concise|verbose|count]";
1120 e->usage =
1121 "Usage: core show channels [concise|verbose|count]\n"
1122 " Lists currently defined channels and some information about them. If\n"
1123 " 'concise' is specified, the format is abridged and in a more easily\n"
1124 " machine parsable format. If 'verbose' is specified, the output includes\n"
1125 " more and longer fields. If 'count' is specified only the channel and call\n"
1126 " count is output.\n";
1127 return NULL;
1128
1129 case CLI_GENERATE:
1130 return NULL;
1131 }
1132
1133 if (a->argc == e->args) {
1134 if (!strcasecmp(a->argv[e->args-1],"concise"))
1135 concise = 1;
1136 else if (!strcasecmp(a->argv[e->args-1],"verbose"))
1137 verbose = 1;
1138 else if (!strcasecmp(a->argv[e->args-1],"count"))
1139 count = 1;
1140 else
1141 return CLI_SHOWUSAGE;
1142 } else if (a->argc != e->args - 1)
1143 return CLI_SHOWUSAGE;
1144
1146
1147 if (!count) {
1148 if (!concise && !verbose)
1149 ast_cli(a->fd, FORMAT_STRING2, "Channel", "Location", "State", "Application(Data)");
1150 else if (verbose)
1151 ast_cli(a->fd, VERBOSE_FORMAT_STRING2, "Channel", "Context", "Extension", "Priority", "State", "Application", "Data",
1152 "CallerID", "Duration", "Accountcode", "PeerAccount", "BridgeID");
1153 }
1154
1155 it_chans = ao2_iterator_init(channels, 0);
1156 for (; (cs = ao2_iterator_next(&it_chans)); ao2_ref(cs, -1)) {
1157 char durbuf[16] = "-";
1158
1159 if (!count) {
1160 if ((concise || verbose) && !ast_tvzero(cs->base->creationtime)) {
1161 int duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->base->creationtime) / 1000);
1162 if (verbose) {
1163 int durh = duration / 3600;
1164 int durm = (duration % 3600) / 60;
1165 int durs = duration % 60;
1166 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
1167 } else {
1168 snprintf(durbuf, sizeof(durbuf), "%d", duration);
1169 }
1170 }
1171 if (concise) {
1173 S_OR(cs->dialplan->appl, "(None)"),
1174 cs->dialplan->data,
1175 cs->caller->number,
1176 cs->base->accountcode,
1177 cs->peer->account,
1178 cs->amaflags,
1179 durbuf,
1180 cs->bridge->id,
1181 cs->base->uniqueid);
1182 } else if (verbose) {
1184 S_OR(cs->dialplan->appl, "(None)"),
1185 S_OR(cs->dialplan->data, "(Empty)"),
1186 cs->caller->number,
1187 durbuf,
1188 cs->base->accountcode,
1189 cs->peer->account,
1190 cs->bridge->id);
1191 } else {
1192 char locbuf[40] = "(None)";
1193 char appdata[40] = "(None)";
1194
1196 snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", cs->dialplan->exten, cs->dialplan->context, cs->dialplan->priority);
1197 }
1198 if (!ast_strlen_zero(cs->dialplan->appl)) {
1199 snprintf(appdata, sizeof(appdata), "%s(%s)", cs->dialplan->appl, S_OR(cs->dialplan->data, ""));
1200 }
1201 ast_cli(a->fd, FORMAT_STRING, cs->base->name, locbuf, ast_state2str(cs->state), appdata);
1202 }
1203 }
1204 }
1205 ao2_iterator_destroy(&it_chans);
1206
1207 if (!concise) {
1208 numchans = ast_active_channels();
1209 ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
1211 ast_cli(a->fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
1213 ((double)ast_active_calls() / (double)ast_option_maxcalls) * 100.0);
1214 else
1215 ast_cli(a->fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
1216
1217 ast_cli(a->fd, "%d call%s processed\n", ast_processed_calls(), ESS(ast_processed_calls()));
1218 }
1219 ao2_ref(channels, -1);
1220
1221 return CLI_SUCCESS;
1222
1223#undef FORMAT_STRING
1224#undef FORMAT_STRING2
1225#undef CONCISE_FORMAT_STRING
1226#undef VERBOSE_FORMAT_STRING
1227#undef VERBOSE_FORMAT_STRING2
1228}
int ast_active_channels(void)
returns number of active/allocated channels
Definition: channel.c:499
const char * ast_state2str(enum ast_channel_state state)
Gives the string form of a given channel state.
Definition: channel.c:636
static struct channel_usage channels
struct ao2_container * ast_channel_cache_by_name(void)
Secondary channel cache, indexed by name.
int ast_option_maxcalls
Definition: options.c:80
#define VERBOSE_FORMAT_STRING2
#define CONCISE_FORMAT_STRING
#define FORMAT_STRING2
#define VERBOSE_FORMAT_STRING
int ast_active_calls(void)
Retrieve the number of active calls.
Definition: pbx.c:4781
int ast_processed_calls(void)
Retrieve the total number of calls processed through the PBX since last restart.
Definition: pbx.c:4786
const ast_string_field accountcode
const ast_string_field uniqueid
const ast_string_field number
const ast_string_field data
const ast_string_field context
const ast_string_field exten
const ast_string_field appl
struct ast_channel_snapshot_dialplan * dialplan
struct ast_channel_snapshot_peer * peer
struct ast_channel_snapshot_bridge * bridge
enum ast_channel_state state
struct ast_channel_snapshot_caller * caller
int args
This gets set in ast_cli_register()
Definition: cli.h:185
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References a, ast_channel_snapshot_peer::account, ast_channel_snapshot_base::accountcode, ast_channel_snapshot::amaflags, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_channel_snapshot_dialplan::appl, ast_cli_entry::args, ast_active_calls(), ast_active_channels(), ast_channel_cache_by_name(), ast_cli(), ast_option_maxcalls, ast_processed_calls(), ast_state2str(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_channel_snapshot::base, ast_channel_snapshot::bridge, ast_channel_snapshot::caller, channels, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, CONCISE_FORMAT_STRING, ast_channel_snapshot_dialplan::context, ast_channel_snapshot_base::creationtime, ast_channel_snapshot_dialplan::data, ast_channel_snapshot::dialplan, ESS, ast_channel_snapshot_dialplan::exten, FORMAT_STRING, FORMAT_STRING2, ast_channel_snapshot_bridge::id, ast_channel_snapshot_base::name, NULL, ast_channel_snapshot_caller::number, ast_channel_snapshot::peer, ast_channel_snapshot_dialplan::priority, S_OR, ast_channel_snapshot::state, ast_channel_snapshot_base::uniqueid, ast_cli_entry::usage, VERBOSE_FORMAT_STRING, and VERBOSE_FORMAT_STRING2.

◆ handle_cli_check_permissions()

static char * handle_cli_check_permissions ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

handles CLI command 'cli check permissions'

Definition at line 1351 of file main/cli.c.

1352{
1353 struct passwd *pw = NULL;
1354 struct group *gr;
1355 int gid = -1, uid = -1;
1356 char command[AST_MAX_ARGS] = "";
1357 struct ast_cli_entry *ce = NULL;
1358 int found = 0;
1359 char *group, *tmp;
1360
1361 switch (cmd) {
1362 case CLI_INIT:
1363 e->command = "cli check permissions";
1364 e->usage =
1365 "Usage: cli check permissions {<username>|@<groupname>|<username>@<groupname>} [<command>]\n"
1366 " Check permissions config for a user@group or list the allowed commands for the specified user.\n"
1367 " The username or the groupname may be omitted.\n";
1368 return NULL;
1369 case CLI_GENERATE:
1370 if (a->pos >= 4) {
1371 return ast_cli_generator(a->line + strlen("cli check permissions") + strlen(a->argv[3]) + 1, a->word, a->n);
1372 }
1373 return NULL;
1374 }
1375
1376 if (a->argc < 4) {
1377 return CLI_SHOWUSAGE;
1378 }
1379
1380 tmp = ast_strdupa(a->argv[3]);
1381 group = strchr(tmp, '@');
1382 if (group) {
1383 gr = getgrnam(&group[1]);
1384 if (!gr) {
1385 ast_cli(a->fd, "Unknown group '%s'\n", &group[1]);
1386 return CLI_FAILURE;
1387 }
1388 group[0] = '\0';
1389 gid = gr->gr_gid;
1390 }
1391
1392 if (!group && ast_strlen_zero(tmp)) {
1393 ast_cli(a->fd, "You didn't supply a username\n");
1394 } else if (!ast_strlen_zero(tmp) && !(pw = getpwnam(tmp))) {
1395 ast_cli(a->fd, "Unknown user '%s'\n", tmp);
1396 return CLI_FAILURE;
1397 } else if (pw) {
1398 uid = pw->pw_uid;
1399 }
1400
1401 if (a->argc == 4) {
1402 while ((ce = cli_next(ce))) {
1403 /* Hide commands that start with '_' */
1404 if (ce->_full_cmd[0] == '_') {
1405 continue;
1406 }
1407 if (cli_has_permissions(uid, gid, ce->_full_cmd)) {
1408 ast_cli(a->fd, "%30.30s %s\n", ce->_full_cmd, S_OR(ce->summary, "<no description available>"));
1409 found++;
1410 }
1411 }
1412 if (!found) {
1413 ast_cli(a->fd, "You are not allowed to run any command on Asterisk\n");
1414 }
1415 } else {
1416 ast_join(command, sizeof(command), a->argv + 4);
1417 ast_cli(a->fd, "%s '%s%s%s' is %s to run command: '%s'\n", uid >= 0 ? "User" : "Group", tmp,
1418 group && uid >= 0 ? "@" : "",
1419 group ? &group[1] : "",
1420 cli_has_permissions(uid, gid, command) ? "allowed" : "not allowed", command);
1421 }
1422
1423 return CLI_SUCCESS;
1424}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
const char *const summary
Definition: cli.h:176

References ast_cli_entry::_full_cmd, a, ast_cli(), ast_cli_generator(), ast_join, AST_MAX_ARGS, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, cli_has_permissions(), CLI_INIT, cli_next(), CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, S_OR, ast_cli_entry::summary, and ast_cli_entry::usage.

◆ handle_cli_malloc_trim()

static char * handle_cli_malloc_trim ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1968 of file main/cli.c.

1969{
1970 extern int malloc_trim(size_t __pad) __THROW;
1971
1972 switch (cmd) {
1973 case CLI_INIT:
1974 e->command = "malloc trim";
1975 e->usage =
1976 "Usage: malloc trim\n"
1977 " Try to give excess memory back to the OS.\n";
1978 return NULL;
1979 case CLI_GENERATE:
1980 return NULL;
1981 }
1982
1983 if (malloc_trim(0)) {
1984 ast_cli(a->fd, "Returned some memory to the OS.\n");
1985 } else {
1986 ast_cli(a->fd, "No memory returned to the OS.\n");
1987 }
1988
1989 return CLI_SUCCESS;
1990}

References a, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ handle_cli_reload_permissions()

static char * handle_cli_reload_permissions ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

handles CLI command 'cli reload permissions'

Definition at line 1332 of file main/cli.c.

1333{
1334 switch (cmd) {
1335 case CLI_INIT:
1336 e->command = "cli reload permissions";
1337 e->usage =
1338 "Usage: cli reload permissions\n"
1339 " Reload the 'cli_permissions.conf' file.\n";
1340 return NULL;
1341 case CLI_GENERATE:
1342 return NULL;
1343 }
1344
1346
1347 return CLI_SUCCESS;
1348}
int ast_cli_perms_init(int reload)
Definition: main/cli.c:2081

References ast_cli_perms_init(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ handle_cli_show_permissions()

static char * handle_cli_show_permissions ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

handles CLI command 'cli show permissions'

Definition at line 1287 of file main/cli.c.

1288{
1289 struct usergroup_cli_perm *cp;
1290 struct cli_perm *perm;
1291 struct passwd *pw = NULL;
1292 struct group *gr = NULL;
1293
1294 switch (cmd) {
1295 case CLI_INIT:
1296 e->command = "cli show permissions";
1297 e->usage =
1298 "Usage: cli show permissions\n"
1299 " Shows CLI configured permissions.\n";
1300 return NULL;
1301 case CLI_GENERATE:
1302 return NULL;
1303 }
1304
1306 AST_LIST_TRAVERSE(&cli_perms, cp, list) {
1307 if (cp->uid >= 0) {
1308 pw = getpwuid(cp->uid);
1309 if (pw) {
1310 ast_cli(a->fd, "user: %s [uid=%d]\n", pw->pw_name, cp->uid);
1311 }
1312 } else {
1313 gr = getgrgid(cp->gid);
1314 if (gr) {
1315 ast_cli(a->fd, "group: %s [gid=%d]\n", gr->gr_name, cp->gid);
1316 }
1317 }
1318 ast_cli(a->fd, "Permissions:\n");
1319 if (cp->perms) {
1320 AST_LIST_TRAVERSE(cp->perms, perm, list) {
1321 ast_cli(a->fd, "\t%s -> %s\n", perm->permit ? "permit" : "deny", perm->command);
1322 }
1323 }
1324 ast_cli(a->fd, "\n");
1325 }
1327
1328 return CLI_SUCCESS;
1329}

References a, ast_cli(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, cli_perm::command, usergroup_cli_perm::gid, NULL, cli_perm::permit, usergroup_cli_perm::perms, usergroup_cli_perm::uid, and ast_cli_entry::usage.

◆ handle_cli_wait_fullybooted()

static char * handle_cli_wait_fullybooted ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1931 of file main/cli.c.

1932{
1933 switch (cmd) {
1934 case CLI_INIT:
1935 e->command = "core waitfullybooted";
1936 e->usage =
1937 "Usage: core waitfullybooted\n"
1938 " Wait until Asterisk has fully booted.\n";
1939 return NULL;
1940 case CLI_GENERATE:
1941 return NULL;
1942 }
1943
1944 while (!ast_fully_booted) {
1945 usleep(100);
1946 }
1947
1948 ast_cli(a->fd, "Asterisk has fully booted.\n");
1949
1950 return CLI_SUCCESS;
1951}
#define ast_fully_booted
Definition: options.h:127

References a, ast_cli(), ast_fully_booted, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ handle_commandmatchesarray()

static char * handle_commandmatchesarray ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1428 of file main/cli.c.

1429{
1430 char *buf, *obuf;
1431 int buflen = 2048;
1432 int len = 0;
1433 char **matches;
1434 int x, matchlen;
1435
1436 switch (cmd) {
1437 case CLI_INIT:
1438 e->command = "_command matchesarray";
1439 e->usage =
1440 "Usage: _command matchesarray \"<line>\" text \n"
1441 " This function is used internally to help with command completion and should.\n"
1442 " never be called by the user directly.\n";
1443 return NULL;
1444 case CLI_GENERATE:
1445 return NULL;
1446 }
1447
1448 if (a->argc != 4)
1449 return CLI_SHOWUSAGE;
1450 if (!(buf = ast_malloc(buflen)))
1451 return CLI_FAILURE;
1452 buf[len] = '\0';
1453 matches = ast_cli_completion_matches(a->argv[2], a->argv[3]);
1454 if (matches) {
1455 for (x=0; matches[x]; x++) {
1456 matchlen = strlen(matches[x]) + 1;
1457 if (len + matchlen >= buflen) {
1458 buflen += matchlen * 3;
1459 obuf = buf;
1460 if (!(buf = ast_realloc(obuf, buflen)))
1461 /* Memory allocation failure... Just free old buffer and be done */
1462 ast_free(obuf);
1463 }
1464 if (buf)
1465 len += sprintf( buf + len, "%s ", matches[x]);
1466 ast_free(matches[x]);
1467 matches[x] = NULL;
1468 }
1469 ast_free(matches);
1470 }
1471
1472 if (buf) {
1473 ast_cli(a->fd, "%s%s",buf, AST_CLI_COMPLETE_EOF);
1474 ast_free(buf);
1475 } else
1476 ast_cli(a->fd, "NULL\n");
1477
1478 return CLI_SUCCESS;
1479}
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:226
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define AST_CLI_COMPLETE_EOF
Definition: cli.h:52
char ** ast_cli_completion_matches(const char *text, const char *word)
Generates a NULL-terminated array of strings that 1) begin with the string in the second parameter,...
Definition: main/cli.c:2681

References a, ast_cli(), AST_CLI_COMPLETE_EOF, ast_cli_completion_matches(), ast_free, ast_malloc, ast_realloc, buf, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, len(), NULL, and ast_cli_entry::usage.

◆ handle_core_reload()

static char * handle_core_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 319 of file main/cli.c.

320{
321 switch (cmd) {
322 case CLI_INIT:
323 e->command = "core reload";
324 e->usage =
325 "Usage: core reload\n"
326 " Execute a global reload.\n";
327 return NULL;
328
329 case CLI_GENERATE:
330 return NULL;
331 }
332
333 if (a->argc != e->args) {
334 return CLI_SHOWUSAGE;
335 }
336
338
339 return CLI_SUCCESS;
340}
enum ast_module_reload_result ast_module_reload(const char *name)
Reload asterisk modules.
Definition: loader.c:1730

References a, ast_cli_entry::args, ast_module_reload(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ handle_core_set_debug_channel()

static char * handle_core_set_debug_channel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1511 of file main/cli.c.

1512{
1513 struct ast_channel *c = NULL;
1514 static const char * const completions_all[] = { "all", NULL };
1515 static const char * const completions_off[] = { "off", NULL };
1516 struct channel_set_debug_args args = {
1517 .fd = a->fd,
1518 };
1519
1520 switch (cmd) {
1521 case CLI_INIT:
1522 e->command = "core set debug channel";
1523 e->usage =
1524 "Usage: core set debug channel <all|channel> [off]\n"
1525 " Enables/disables debugging on all or on a specific channel.\n";
1526 return NULL;
1527 case CLI_GENERATE:
1528 if (a->pos == 4) {
1529 char *complete = ast_cli_complete(a->word, completions_all, a->n);
1530 if (!complete) {
1531 complete = ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
1532 }
1533 return complete;
1534 } else if (a->pos == 5) {
1535 return ast_cli_complete(a->word, completions_off, a->n);
1536 }
1537
1538 return NULL;
1539 }
1540
1541 if (a->argc == e->args + 2) {
1542 /* 'core set debug channel {all|chan_id}' */
1543 if (!strcasecmp(a->argv[e->args + 1], "off"))
1544 args.is_off = 1;
1545 else
1546 return CLI_SHOWUSAGE;
1547 } else if (a->argc != e->args + 1) {
1548 return CLI_SHOWUSAGE;
1549 }
1550
1551 if (!strcasecmp("all", a->argv[e->args])) {
1552 if (args.is_off) {
1553 global_fin &= ~DEBUGCHAN_FLAG;
1554 global_fout &= ~DEBUGCHAN_FLAG;
1555 } else {
1558 }
1560 } else {
1561 if ((c = ast_channel_get_by_name(a->argv[e->args]))) {
1564 } else {
1565 ast_cli(a->fd, "No such channel %s\n", a->argv[e->args]);
1566 }
1567 }
1568
1569 ast_cli(a->fd, "Debugging on new channels is %s\n", args.is_off ? "disabled" : "enabled");
1570
1571 return CLI_SUCCESS;
1572}
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
struct ast_channel * ast_channel_callback(ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
Call a function with every active channel.
Definition: channel.c:1317
unsigned long global_fin
Definition: channel.c:98
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition: channel.c:1398
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3008
unsigned long global_fout
Definition: channel.h:886
static int channel_set_debug(void *obj, void *arg, void *data, int flags)
Definition: main/cli.c:1487
char * ast_cli_complete(const char *word, const char *const choices[], int state)
Definition: main/cli.c:1823
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:1842
static struct test_val c

References a, ast_cli_entry::args, args, ast_channel_callback(), ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_cli_complete(), ast_complete_channels(), c, channel_set_debug(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, DEBUGCHAN_FLAG, global_fin, global_fout, NULL, OBJ_MULTIPLE, OBJ_NODATA, and ast_cli_entry::usage.

◆ handle_debug()

static char * handle_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 572 of file main/cli.c.

573{
574 int atleast = 0;
575 const char *argv3 = a->argv ? S_OR(a->argv[3], "") : "";
576
577 switch (cmd) {
578 case CLI_INIT:
579 e->command = "core set debug";
580 e->usage =
581 "Usage: core set debug [atleast] <level> [module]\n"
582 " core set debug off\n"
583 "\n"
584 " Sets level of debug messages to be displayed or\n"
585 " sets a module name to display debug messages from.\n"
586 " 0 or off means no messages should be displayed.\n"
587 " Equivalent to -d[d[...]] on startup\n";
588 return NULL;
589
590 case CLI_GENERATE:
591 if (!strcasecmp(argv3, "category")) {
592 return NULL;
593 }
594
595 if (!strcasecmp(argv3, "atleast")) {
596 atleast = 1;
597 }
598 if (a->pos == 3 || (a->pos == 4 && atleast)) {
599 const char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], "");
600 int numbermatch = (ast_strlen_zero(pos) || strchr("123456789", pos[0])) ? 0 : 21;
601
602 if (a->n < 21 && numbermatch == 0) {
603 return complete_number(pos, 0, 0x7fffffff, a->n);
604 } else if (pos[0] == '0') {
605 if (a->n == 0) {
606 return ast_strdup("0");
607 }
608 } else if (a->n == (21 - numbermatch)) {
609 if (a->pos == 3 && !strncasecmp(argv3, "off", strlen(argv3))) {
610 return ast_strdup("off");
611 } else if (a->pos == 3 && !strncasecmp(argv3, "atleast", strlen(argv3))) {
612 return ast_strdup("atleast");
613 }
614 } else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) {
615 return ast_strdup("atleast");
616 }
617 } else if ((a->pos == 4 && !atleast && strcasecmp(argv3, "off") && strcasecmp(argv3, "channel"))
618 || (a->pos == 5 && atleast)) {
619 return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_RUNNING);
620 }
621 return NULL;
622 }
623 /* all the above return, so we proceed with the handler.
624 * we are guaranteed to be called with argc >= e->args;
625 */
626
627 return handle_debug_or_trace(DEBUG_HANDLER, e, cmd, a);
628}
static char * handle_debug_or_trace(int handler, struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/cli.c:449
#define DEBUG_HANDLER
Definition: main/cli.c:403
static char * complete_number(const char *partial, unsigned int min, unsigned int max, int n)
Definition: main/cli.c:363
char * ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, enum ast_module_helper_type type)
Match modules names for the Asterisk cli.
Definition: loader.c:1537
@ AST_MODULE_HELPER_RUNNING
Definition: module.h:137

References a, ast_module_helper(), AST_MODULE_HELPER_RUNNING, ast_strdup, ast_strlen_zero(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, complete_number(), DEBUG_HANDLER, handle_debug_or_trace(), NULL, S_OR, and ast_cli_entry::usage.

◆ handle_debug_category()

static char * handle_debug_category ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1574 of file main/cli.c.

1575{
1576 const char *argv4 = a->argv ? S_OR(a->argv[4], "") : "";
1577 int offset = strncasecmp(argv4, "off", strlen(argv4)) ? 0 : 1;
1578
1579 switch (cmd) {
1580 case CLI_INIT:
1581 e->command = "core set debug category";
1582 e->usage =
1583 "Usage: core set debug category <category>[:<sublevel>] [category[:<sublevel] ...]\n"
1584 " core set debug category off [<category> [<category>] ...]\n\n"
1585 " Allows enabling and disabling debug logging categories.\n"
1586 " When a category is enabled all relevant debug messages are logged\n"
1587 " for a given category. However, if a sublevel is specified only\n"
1588 " those categorized messages at or below the coded debug sublevel\n"
1589 " are logged.\n";
1590 return NULL;
1591
1592 case CLI_GENERATE:
1593 if (a->pos < e->args) {
1594 return NULL;
1595 }
1596
1597 if (a->pos == 4 && offset) {
1599 }
1600
1601 return ast_debug_category_complete(a->argv + 4,
1602 a->pos - e->args, a->word, a->n - 1);
1603 }
1604
1605 if (a->argc <= e->args) {
1606 return CLI_SHOWUSAGE;
1607 }
1608
1609 ast_debug_category_set_sublevels(a->argv + e->args + offset, a->argc - e->args - offset,
1611
1612 return CLI_SUCCESS;
1613}
#define AST_LOG_CATEGORY_DISABLED
#define AST_LOG_CATEGORY_ENABLED
char * ast_debug_category_complete(const char *const *argv, int argc, const char *word, int state)
Add a unique (no duplicates) result to a request for completion for debug categories.
int ast_debug_category_set_sublevels(const char *const *names, size_t size, int default_sublevel)
Set one or more debug category's sublevel.

References a, ast_cli_entry::args, ast_cli_completion_add(), ast_debug_category_complete(), ast_debug_category_set_sublevels(), AST_LOG_CATEGORY_DISABLED, AST_LOG_CATEGORY_ENABLED, ast_strdup, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, S_OR, and ast_cli_entry::usage.

◆ handle_debug_or_trace()

static char * handle_debug_or_trace ( int  handler,
struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 449 of file main/cli.c.

450{
451 int oldval;
452 int newlevel;
453 int atleast = 0;
454 struct module_level *ml;
455 struct module_level_list *modules;
456 unsigned int module_option;
457 int *core_option;
458 const char *handler_name;
459
460 if (a->argc <= e->args) {
461 return CLI_SHOWUSAGE;
462 }
463
464 if (handler == DEBUG_HANDLER) {
465 modules = &debug_modules;
466 module_option = AST_OPT_FLAG_DEBUG_MODULE;
467 core_option = &option_debug;
468 handler_name = "debug";
469 } else {
470 modules = &trace_modules;
471 module_option = AST_OPT_FLAG_TRACE_MODULE;
472 core_option = &option_trace;
473 handler_name = "trace";
474 }
475
476 if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args], "off")) {
477 newlevel = 0;
478 } else {
479 if (!strcasecmp(a->argv[e->args], "atleast")) {
480 atleast = 1;
481 }
482
483 if (a->argc != e->args + atleast + 1 && a->argc != e->args + atleast + 2) {
484 return CLI_SHOWUSAGE;
485 }
486
487 if (sscanf(a->argv[e->args + atleast], "%30d", &newlevel) != 1) {
488 return CLI_SHOWUSAGE;
489 }
490
491 if (a->argc == e->args + atleast + 2) {
492 /* We have specified a module name. */
493 char *mod = ast_strdupa(a->argv[e->args + atleast + 1]);
494 int mod_len = strlen(mod);
495
496 if (3 < mod_len && !strcasecmp(mod + mod_len - 3, ".so")) {
497 mod[mod_len - 3] = '\0';
498 }
499
500 AST_RWLIST_WRLOCK(modules);
501
502 ml = find_module_level(mod, modules);
503 if (!newlevel) {
504 if (!ml) {
505 /* Specified off for a nonexistent entry. */
506 AST_RWLIST_UNLOCK(modules);
507 ast_cli(a->fd, "Core %s is still 0 for '%s'.\n", handler_name, mod);
508 return CLI_SUCCESS;
509 }
510 AST_RWLIST_REMOVE(modules, ml, entry);
511 if (AST_RWLIST_EMPTY(modules)) {
512 ast_clear_flag64(&ast_options, module_option);
513 }
514 AST_RWLIST_UNLOCK(modules);
515 ast_cli(a->fd, "Core %s was %u and has been set to 0 for '%s'.\n", handler_name,
516 ml->level, mod);
517 ast_free(ml);
518 return CLI_SUCCESS;
519 }
520
521 if (ml) {
522 if ((atleast && newlevel < ml->level) || ml->level == newlevel) {
523 ast_cli(a->fd, "Core %s is still %u for '%s'.\n", handler_name, ml->level, mod);
524 AST_RWLIST_UNLOCK(modules);
525 return CLI_SUCCESS;
526 }
527 oldval = ml->level;
528 ml->level = newlevel;
529 } else {
530 ml = ast_calloc(1, sizeof(*ml) + strlen(mod) + 1);
531 if (!ml) {
532 AST_RWLIST_UNLOCK(modules);
533 return CLI_FAILURE;
534 }
535 oldval = ml->level;
536 ml->level = newlevel;
537 strcpy(ml->module, mod);
538 AST_RWLIST_INSERT_TAIL(modules, ml, entry);
539 }
540 ast_set_flag64(&ast_options, module_option);
541
542 ast_cli(a->fd, "Core %s was %d and has been set to %u for '%s'.\n", handler_name,
543 oldval, ml->level, ml->module);
544
545 AST_RWLIST_UNLOCK(modules);
546
547 return CLI_SUCCESS;
548 }
549 }
550
551 /* Update global debug level */
552 if (!newlevel) {
553 /* Specified level was 0 or off. */
554 AST_RWLIST_WRLOCK(modules);
555 while ((ml = AST_RWLIST_REMOVE_HEAD(modules, entry))) {
556 ast_free(ml);
557 }
559 AST_RWLIST_UNLOCK(modules);
560 }
561 oldval = *core_option;
562 if (!atleast || newlevel > *core_option) {
563 *core_option = newlevel;
564 }
565
566 /* Report debug level status */
567 status_debug_verbose(a, handler, oldval, *core_option);
568
569 return CLI_SUCCESS;
570}
int option_debug
Definition: options.c:70
struct ast_flags64 ast_options
Definition: options.c:62
int option_trace
Definition: options.c:72
@ AST_OPT_FLAG_TRACE_MODULE
Definition: options.h:89
@ AST_OPT_FLAG_DEBUG_MODULE
Definition: options.h:87
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:452
#define AST_RWLIST_REMOVE_HEAD
Definition: linkedlists.h:844
static struct module_level_list trace_modules
Definition: main/cli.c:108
static void status_debug_verbose(struct ast_cli_args *a, int handler, int old_val, int cur_val)
Definition: main/cli.c:407
static struct module_level * find_module_level(const char *module, struct module_level_list *mll)
Find the module level setting.
Definition: main/cli.c:351
static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Definition: test_ari.c:59
#define ast_clear_flag64(p, flag)
Definition: utils.h:151
#define ast_set_flag64(p, flag)
Definition: utils.h:144

References a, ast_cli_entry::args, ast_calloc, ast_clear_flag64, ast_cli(), ast_free, AST_OPT_FLAG_DEBUG_MODULE, AST_OPT_FLAG_TRACE_MODULE, ast_options, AST_RWLIST_EMPTY, AST_RWLIST_INSERT_TAIL, AST_RWLIST_REMOVE, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_set_flag64, ast_strdupa, CLI_FAILURE, CLI_SHOWUSAGE, CLI_SUCCESS, DEBUG_HANDLER, debug_modules, find_module_level(), handler(), module_level::level, option_debug, option_trace, status_debug_verbose(), and trace_modules.

Referenced by handle_debug(), and handle_trace().

◆ handle_help()

static char * handle_help ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2563 of file main/cli.c.

2564{
2565 char fullcmd[80];
2566 struct ast_cli_entry *my_e;
2567 char *res = CLI_SUCCESS;
2568
2569 if (cmd == CLI_INIT) {
2570 e->command = "core show help";
2571 e->usage =
2572 "Usage: core show help [topic]\n"
2573 " When called with a topic as an argument, displays usage\n"
2574 " information on the given command. If called without a\n"
2575 " topic, it provides a list of commands.\n";
2576 return NULL;
2577
2578 } else if (cmd == CLI_GENERATE) {
2579 /* skip first 14 or 15 chars, "core show help " */
2580 int l = strlen(a->line);
2581
2582 if (l > 15) {
2583 l = 15;
2584 }
2585 /* XXX watch out, should stop to the non-generator parts */
2586 return __ast_cli_generator(a->line + l, a->word, a->n, 0);
2587 }
2588 if (a->argc == e->args) {
2589 return help1(a->fd, NULL, 0);
2590 }
2591
2593 my_e = find_cli(a->argv + 3, 1); /* try exact match first */
2594 if (!my_e) {
2595 res = help1(a->fd, a->argv + 3, 1 /* locked */);
2597 return res;
2598 }
2599 if (my_e->usage)
2600 ast_cli(a->fd, "%s", my_e->usage);
2601 else {
2602 ast_join(fullcmd, sizeof(fullcmd), a->argv + 3);
2603 ast_cli(a->fd, "No help text available for '%s'.\n", fullcmd);
2604 }
2606 return res;
2607}
static char * help1(int fd, const char *const match[], int locked)
helper for final part of handle_help if locked = 1, assume the list is already locked
Definition: main/cli.c:2533

References __ast_cli_generator(), a, ast_cli_entry::args, ast_cli(), ast_join, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, find_cli(), help1(), NULL, and ast_cli_entry::usage.

◆ handle_load()

static char * handle_load ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 240 of file main/cli.c.

241{
242 /* "module load <mod>" */
243 switch (cmd) {
244 case CLI_INIT:
245 e->command = "module load";
246 e->usage =
247 "Usage: module load <module name>\n"
248 " Loads the specified module into Asterisk.\n";
249 return NULL;
250
251 case CLI_GENERATE:
252 if (a->pos != e->args) {
253 return NULL;
254 }
255 return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_LOAD);
256 }
257 if (a->argc != e->args + 1) {
258 return CLI_SHOWUSAGE;
259 }
260 if (ast_load_resource(a->argv[e->args])) {
261 ast_cli(a->fd, "Unable to load module %s\n", a->argv[e->args]);
262 return CLI_FAILURE;
263 }
264 ast_cli(a->fd, "Loaded %s\n", a->argv[e->args]);
265 return CLI_SUCCESS;
266}
enum ast_module_load_result ast_load_resource(const char *resource_name)
Load a module.
Definition: loader.c:1987
@ AST_MODULE_HELPER_LOAD
Definition: module.h:133

References a, ast_cli_entry::args, ast_cli(), ast_load_resource(), ast_module_helper(), AST_MODULE_HELPER_LOAD, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ handle_logger_mute()

static char * handle_logger_mute ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 783 of file main/cli.c.

784{
785 switch (cmd) {
786 case CLI_INIT:
787 e->command = "logger mute";
788 e->usage =
789 "Usage: logger mute\n"
790 " Disables logging output to the current console, making it possible to\n"
791 " gather information without being disturbed by scrolling lines.\n";
792 return NULL;
793 case CLI_GENERATE:
794 return NULL;
795 }
796
797 if (a->argc < 2 || a->argc > 3)
798 return CLI_SHOWUSAGE;
799
800 if (a->argc == 3 && !strcasecmp(a->argv[2], "silent"))
802 else
804
805 return CLI_SUCCESS;
806}
void ast_console_toggle_mute(int fd, int silent)
mute or unmute a console from logging
Definition: asterisk.c:1286

References a, ast_console_toggle_mute(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ handle_modlist()

static char * handle_modlist ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1008 of file main/cli.c.

1009{
1010 const char *like;
1011
1012 switch (cmd) {
1013 case CLI_INIT:
1014 e->command = "module show [like]";
1015 e->usage =
1016 "Usage: module show [like keyword]\n"
1017 " Shows Asterisk modules currently in use, and usage statistics.\n";
1018 return NULL;
1019
1020 case CLI_GENERATE:
1021 if (a->pos == e->args) {
1022 return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_LOADED);
1023 } else {
1024 return NULL;
1025 }
1026 }
1027 /* all the above return, so we proceed with the handler.
1028 * we are guaranteed to have argc >= e->args
1029 */
1030 if (a->argc == e->args - 1)
1031 like = "";
1032 else if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args-1], "like") )
1033 like = a->argv[e->args];
1034 else
1035 return CLI_SHOWUSAGE;
1036
1038 climodentryfd = a->fd; /* global, protected by climodentrylock */
1039 ast_cli(a->fd, MODLIST_FORMAT2, "Module", "Description", "Use Count", "Status", "Support Level");
1040 ast_cli(a->fd,"%d modules loaded\n", ast_update_module_list(modlist_modentry, like));
1041 climodentryfd = -1;
1043 return CLI_SUCCESS;
1044}
#define ast_mutex_lock(a)
Definition: lock.h:196
static int modlist_modentry(const char *module, const char *description, int usecnt, const char *status, const char *like, enum ast_module_support_level support_level)
Definition: main/cli.c:900
static int climodentryfd
Definition: main/cli.c:898
#define MODLIST_FORMAT2
Definition: main/cli.c:895
static ast_mutex_t climodentrylock
Definition: main/cli.c:897
int ast_update_module_list(int(*modentry)(const char *module, const char *description, int usecnt, const char *status, const char *like, enum ast_module_support_level support_level), const char *like)
Ask for a list of modules, descriptions, use counts and status.
Definition: loader.c:2746
@ AST_MODULE_HELPER_LOADED
Definition: module.h:129

References a, ast_cli_entry::args, ast_cli(), ast_module_helper(), AST_MODULE_HELPER_LOADED, ast_mutex_lock, ast_mutex_unlock, ast_update_module_list(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, climodentryfd, climodentrylock, ast_cli_entry::command, MODLIST_FORMAT2, modlist_modentry(), NULL, and ast_cli_entry::usage.

◆ handle_refresh()

static char * handle_refresh ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 808 of file main/cli.c.

809{
810 static const char * const completions[] = { "recursively", NULL };
811 int res;
812 /* "module refresh <mod>" */
813 switch (cmd) {
814 case CLI_INIT:
815 e->command = "module refresh";
816 e->usage =
817 "Usage: module refresh <module name> [recursively]\n"
818 " Unloads and loads the specified module into Asterisk.\n"
819 " 'recursively' will attempt to unload any modules with\n"
820 " dependencies on this module for you and load them again\n"
821 " afterwards.\n";
822 return NULL;
823
824 case CLI_GENERATE:
825 if (a->pos == e->args) {
826 return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_UNLOAD);
827 } else if (a->pos == e->args + 1) {
828 return ast_cli_complete(a->word, completions, a->n);
829 }
830 return NULL;
831 }
832 if (a->argc < 3 || a->argc > 4) {
833 return CLI_SHOWUSAGE;
834 }
835
836 res = ast_refresh_resource(a->argv[e->args], AST_FORCE_SOFT, a->argc == 4 && !strcasecmp(a->argv[3], "recursively"));
837 if (res) {
838 ast_cli(a->fd, "Unable to %s resource %s\n", res > 0 ? "unload" : "load", a->argv[e->args]);
839 return CLI_FAILURE;
840 }
841 ast_cli(a->fd, "Unloaded and loaded %s\n", a->argv[e->args]);
842 return CLI_SUCCESS;
843}
int ast_refresh_resource(const char *resource_name, enum ast_module_unload_mode force, int recursive)
Unload and load a module again.
Definition: loader.c:1416
@ AST_FORCE_SOFT
Definition: module.h:62
@ AST_MODULE_HELPER_UNLOAD
Definition: module.h:135

References a, ast_cli_entry::args, ast_cli(), ast_cli_complete(), AST_FORCE_SOFT, ast_module_helper(), AST_MODULE_HELPER_UNLOAD, ast_refresh_resource(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ handle_reload()

static char * handle_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 268 of file main/cli.c.

269{
270 int x;
271
272 switch (cmd) {
273 case CLI_INIT:
274 e->command = "module reload";
275 e->usage =
276 "Usage: module reload [module ...]\n"
277 " Reloads configuration files for all listed modules which support\n"
278 " reloading, or for all supported modules if none are listed.\n";
279 return NULL;
280
281 case CLI_GENERATE:
282 return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_RELOAD);
283 }
284 if (a->argc == e->args) {
286 return CLI_SUCCESS;
287 }
288 for (x = e->args; x < a->argc; x++) {
289 enum ast_module_reload_result res = ast_module_reload(a->argv[x]);
290 switch (res) {
292 ast_cli(a->fd, "No such module '%s'\n", a->argv[x]);
293 break;
295 ast_cli(a->fd, "The module '%s' does not support reloads\n", a->argv[x]);
296 break;
298 ast_cli(a->fd, "Asterisk cannot reload a module yet; request queued\n");
299 break;
301 ast_cli(a->fd, "The module '%s' reported a reload failure\n", a->argv[x]);
302 break;
304 ast_cli(a->fd, "A module reload request is already in progress; please be patient\n");
305 break;
307 ast_cli(a->fd, "The module '%s' was not properly initialized. Before reloading"
308 " the module, you must run \"module load %s\" and fix whatever is"
309 " preventing the module from being initialized.\n", a->argv[x], a->argv[x]);
310 break;
312 ast_cli(a->fd, "Module '%s' reloaded successfully.\n", a->argv[x]);
313 break;
314 }
315 }
316 return CLI_SUCCESS;
317}
ast_module_reload_result
Possible return types for ast_module_reload.
Definition: module.h:109
@ AST_MODULE_RELOAD_IN_PROGRESS
Definition: module.h:114
@ AST_MODULE_RELOAD_QUEUED
Definition: module.h:111
@ AST_MODULE_RELOAD_SUCCESS
Definition: module.h:110
@ AST_MODULE_RELOAD_ERROR
Definition: module.h:113
@ AST_MODULE_RELOAD_NOT_IMPLEMENTED
Definition: module.h:116
@ AST_MODULE_RELOAD_NOT_FOUND
Definition: module.h:112
@ AST_MODULE_RELOAD_UNINITIALIZED
Definition: module.h:115
@ AST_MODULE_HELPER_RELOAD
Definition: module.h:131

References a, ast_cli_entry::args, ast_cli(), ast_module_helper(), AST_MODULE_HELPER_RELOAD, ast_module_reload(), AST_MODULE_RELOAD_ERROR, AST_MODULE_RELOAD_IN_PROGRESS, AST_MODULE_RELOAD_NOT_FOUND, AST_MODULE_RELOAD_NOT_IMPLEMENTED, AST_MODULE_RELOAD_QUEUED, AST_MODULE_RELOAD_SUCCESS, AST_MODULE_RELOAD_UNINITIALIZED, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ handle_showcalls()

static char * handle_showcalls ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1048 of file main/cli.c.

1049{
1050 static const char * const completions[] = { "seconds", NULL };
1051 struct timeval curtime = ast_tvnow();
1052 int showuptime, printsec;
1053
1054 switch (cmd) {
1055 case CLI_INIT:
1056 e->command = "core show calls [uptime]";
1057 e->usage =
1058 "Usage: core show calls [uptime [seconds]]\n"
1059 " Lists number of currently active calls and total number of calls\n"
1060 " processed through PBX since last restart. If 'uptime' is specified\n"
1061 " the system uptime is also displayed. If 'seconds' is specified in\n"
1062 " addition to 'uptime', the system uptime is displayed in seconds.\n";
1063 return NULL;
1064
1065 case CLI_GENERATE:
1066 if (a->pos != e->args)
1067 return NULL;
1068 return ast_cli_complete(a->word, completions, a->n);
1069 }
1070
1071 /* regular handler */
1072 if (a->argc >= e->args && !strcasecmp(a->argv[e->args-1],"uptime")) {
1073 showuptime = 1;
1074
1075 if (a->argc == e->args+1 && !strcasecmp(a->argv[e->args],"seconds"))
1076 printsec = 1;
1077 else if (a->argc == e->args)
1078 printsec = 0;
1079 else
1080 return CLI_SHOWUSAGE;
1081 } else if (a->argc == e->args-1) {
1082 showuptime = 0;
1083 printsec = 0;
1084 } else
1085 return CLI_SHOWUSAGE;
1086
1087 if (ast_option_maxcalls) {
1088 ast_cli(a->fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
1090 ((double)ast_active_calls() / (double)ast_option_maxcalls) * 100.0);
1091 } else {
1092 ast_cli(a->fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
1093 }
1094
1095 ast_cli(a->fd, "%d call%s processed\n", ast_processed_calls(), ESS(ast_processed_calls()));
1096
1097 if (ast_startuptime.tv_sec && showuptime) {
1098 print_uptimestr(a->fd, ast_tvsub(curtime, ast_startuptime), "System uptime: ", printsec);
1099 }
1100
1101 return RESULT_SUCCESS;
1102}
struct timeval ast_startuptime
Definition: asterisk.c:343
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: extconf.c:2297

References a, ast_cli_entry::args, ast_active_calls(), ast_cli(), ast_cli_complete(), ast_option_maxcalls, ast_processed_calls(), ast_startuptime, ast_tvnow(), ast_tvsub(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, ESS, NULL, print_uptimestr(), RESULT_SUCCESS, and ast_cli_entry::usage.

◆ handle_showchan()

static char * handle_showchan ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

< Buffer for CDR variables.

< Accumulation buffer for all output.

Definition at line 1615 of file main/cli.c.

1616{
1617 struct ast_channel *chan;
1618 struct timeval now;
1619 char cdrtime[256];
1620 struct ast_str *obuf;/*!< Buffer for CDR variables. */
1621 struct ast_str *output;/*!< Accumulation buffer for all output. */
1622 long elapsed_seconds=0;
1623 int hour=0, min=0, sec=0;
1624 struct ast_var_t *var;
1625 struct ast_str *write_transpath = ast_str_alloca(256);
1626 struct ast_str *read_transpath = ast_str_alloca(256);
1627 struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1628 struct ast_bridge *bridge;
1630 char callid_buf[32];
1631 int stream_num;
1632 RAII_VAR(char *, tenant_id, NULL, ast_free);
1633
1634 switch (cmd) {
1635 case CLI_INIT:
1636 e->command = "core show channel";
1637 e->usage =
1638 "Usage: core show channel <channel>\n"
1639 " Shows lots of information about the specified channel.\n";
1640 return NULL;
1641 case CLI_GENERATE:
1642 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
1643 }
1644
1645 if (a->argc != 4) {
1646 return CLI_SHOWUSAGE;
1647 }
1648
1649 obuf = ast_str_thread_get(&ast_str_thread_global_buf, 16);
1650 if (!obuf) {
1651 return CLI_FAILURE;
1652 }
1653
1654 chan = ast_channel_get_by_name(a->argv[3]);
1655 if (!chan) {
1656 ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
1657
1658 return CLI_SUCCESS;
1659 }
1660
1661 output = ast_str_create(8192);
1662 if (!output) {
1663 ast_channel_unref(chan);
1664
1665 return CLI_FAILURE;
1666 }
1667
1668 now = ast_tvnow();
1669 ast_channel_lock(chan);
1670
1672 elapsed_seconds = now.tv_sec - ast_channel_creationtime(chan).tv_sec;
1673 hour = elapsed_seconds / 3600;
1674 min = (elapsed_seconds % 3600) / 60;
1675 sec = elapsed_seconds % 60;
1676 snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
1677 } else {
1678 strcpy(cdrtime, "N/A");
1679 }
1680
1681 ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath);
1682 ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath);
1683
1684 bridge = ast_channel_get_bridge(chan);
1685 callid_buf[0] = '\0';
1686 callid = ast_channel_callid(chan);
1687 if (callid) {
1688 ast_callid_strnprint(callid_buf, sizeof(callid_buf), callid);
1689 }
1690
1692 ast_asprintf(&tenant_id, " TenantID: %s\n", ast_channel_tenantid(chan));
1693 }
1694
1695 ast_str_append(&output, 0,
1696 " -- General --\n"
1697 " Name: %s\n"
1698 " Type: %s\n"
1699 " UniqueID: %s\n"
1700 " LinkedID: %s\n"
1701 "%s"
1702 " Caller ID: %s\n"
1703 " Caller ID Name: %s\n"
1704 "Connected Line ID: %s\n"
1705 "Connected Line ID Name: %s\n"
1706 "Eff. Connected Line ID: %s\n"
1707 "Eff. Connected Line ID Name: %s\n"
1708 " DNID Digits: %s\n"
1709 " Language: %s\n"
1710 " State: %s (%u)\n"
1711 " NativeFormats: %s\n"
1712 " WriteFormat: %s\n"
1713 " ReadFormat: %s\n"
1714 " WriteTranscode: %s %s\n"
1715 " ReadTranscode: %s %s\n"
1716 " Time to Hangup: %ld\n"
1717 " Elapsed Time: %s\n"
1718 " Bridge ID: %s\n"
1719 " -- PBX --\n"
1720 " Context: %s\n"
1721 " Extension: %s\n"
1722 " Priority: %d\n"
1723 " Call Group: %llu\n"
1724 " Pickup Group: %llu\n"
1725 " Application: %s\n"
1726 " Data: %s\n"
1727 " Call Identifier: %s\n",
1728 ast_channel_name(chan),
1729 ast_channel_tech(chan)->type,
1732 !ast_strlen_zero(tenant_id) ? tenant_id : "",
1733 S_COR(ast_channel_caller(chan)->id.number.valid,
1734 ast_channel_caller(chan)->id.number.str, "(N/A)"),
1735 S_COR(ast_channel_caller(chan)->id.name.valid,
1736 ast_channel_caller(chan)->id.name.str, "(N/A)"),
1737 S_COR(ast_channel_connected(chan)->id.number.valid,
1738 ast_channel_connected(chan)->id.number.str, "(N/A)"),
1739 S_COR(ast_channel_connected(chan)->id.name.valid,
1740 ast_channel_connected(chan)->id.name.str, "(N/A)"),
1742 ast_channel_connected_effective_id(chan).number.str, "(N/A)"),
1744 ast_channel_connected_effective_id(chan).name.str, "(N/A)"),
1745 S_OR(ast_channel_dialed(chan)->number.str, "(N/A)"),
1748 ast_channel_state(chan),
1752 ast_str_strlen(write_transpath) ? "Yes" : "No",
1753 ast_str_buffer(write_transpath),
1754 ast_str_strlen(read_transpath) ? "Yes" : "No",
1755 ast_str_buffer(read_transpath),
1756 (long)ast_channel_whentohangup(chan)->tv_sec,
1757 cdrtime,
1758 bridge ? bridge->uniqueid : "(Not bridged)",
1759 ast_channel_context(chan),
1760 ast_channel_exten(chan),
1764 S_OR(ast_channel_appl(chan), "(N/A)"),
1765 S_OR(ast_channel_data(chan), "(Empty)"),
1766 S_OR(callid_buf, "(None)")
1767 );
1768
1769 ast_str_append(&output, 0, " Variables:\n");
1770
1771 AST_LIST_TRAVERSE(ast_channel_varshead(chan), var, entries) {
1772 ast_str_append(&output, 0, "%s=%s\n", ast_var_name(var), ast_var_value(var));
1773 }
1774
1775 if (!(ast_channel_tech(chan)->properties & AST_CHAN_TP_INTERNAL)
1776 && ast_cdr_serialize_variables(ast_channel_name(chan), &obuf, '=', '\n')) {
1777 ast_str_append(&output, 0, " CDR Variables:\n%s\n", ast_str_buffer(obuf));
1778 }
1779
1780 ast_str_append(&output, 0, " -- Streams --\n");
1781 for (stream_num = 0; stream_num < ast_stream_topology_get_count(ast_channel_get_stream_topology(chan)); stream_num++) {
1783 struct ast_variable *metadata = ast_stream_get_metadata_list(stream);
1784
1785 ast_str_append(&output, 0,
1786 "Name: %s\n"
1787 " Type: %s\n"
1788 " State: %s\n"
1789 " Group: %d\n"
1790 " Formats: %s\n"
1791 " Metadata:\n",
1792 ast_stream_get_name(stream),
1795 ast_stream_get_group(stream),
1797 );
1798
1799 if (metadata) {
1800 struct ast_variable *v;
1801 for(v = metadata; v; v = v->next) {
1802 ast_str_append(&output, 0, " %s: %s\n", v->name, v->value);
1803 }
1804 ast_variables_destroy(metadata);
1805 }
1806 }
1807
1808 ast_channel_unlock(chan);
1809
1810 ast_cli(a->fd, "%s", ast_str_buffer(output));
1811 ast_free(output);
1812
1813 ao2_cleanup(bridge);
1814 ast_channel_unref(chan);
1815
1816 return CLI_SUCCESS;
1817}
#define var
Definition: ast_expr2f.c:605
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep)
Serializes all the data and variables for a current CDR record.
Definition: cdr.c:3499
static const char type[]
Definition: chan_ooh323.c:109
const char * ast_channel_linkedid(const struct ast_channel *chan)
const char * ast_channel_data(const struct ast_channel *chan)
struct varshead * ast_channel_varshead(struct ast_channel *chan)
const char * ast_channel_tenantid(const struct ast_channel *chan)
struct ast_trans_pvt * ast_channel_readtrans(const struct ast_channel *chan)
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
struct ast_trans_pvt * ast_channel_writetrans(const struct ast_channel *chan)
ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
ast_callid ast_channel_callid(const struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
const char * ast_channel_appl(const struct ast_channel *chan)
struct timeval ast_channel_creationtime(struct ast_channel *chan)
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
Definition: channel.c:10548
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
struct timeval * ast_channel_whentohangup(struct ast_channel *chan)
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
ast_group_t ast_channel_callgroup(const struct ast_channel *chan)
struct ast_party_id ast_channel_connected_effective_id(struct ast_channel *chan)
const char * ast_channel_language(const struct ast_channel *chan)
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
const char * ast_channel_exten(const struct ast_channel *chan)
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
@ AST_CHAN_TP_INTERNAL
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition: channel.h:991
ast_channel_state
ast_channel states
Definition: channelstate.h:35
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:348
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:324
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:734
static const char name[]
Definition: format_mp3.c:68
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
void ast_callid_strnprint(char *buffer, size_t buffer_size, ast_callid callid)
copy a string representation of the callid into a target string
Definition: logger.c:2258
unsigned int ast_callid
const char * ast_stream_get_name(const struct ast_stream *stream)
Get the name of a stream.
Definition: stream.c:309
const char * ast_stream_state2str(enum ast_stream_state state)
Convert the state of a stream into a string.
Definition: stream.c:388
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:791
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:768
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
int ast_stream_get_group(const struct ast_stream *stream)
Get the stream group that a stream is part of.
Definition: stream.c:1080
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
struct ast_variable * ast_stream_get_metadata_list(const struct ast_stream *stream)
Get all stream metadata keys.
Definition: stream.c:439
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
Definition: stream.c:330
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:1139
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
#define ast_str_alloca(init_len)
Definition: strings.h:848
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
Structure that contains information about a bridge.
Definition: bridge.h:353
ast_callid callid
Definition: bridge.h:365
const ast_string_field uniqueid
Definition: bridge.h:405
Number structure.
Definition: app_followme.c:157
const char * ast_translate_path_to_str(struct ast_trans_pvt *t, struct ast_str **str)
Puts a string representation of the translation path into outbuf.
Definition: translate.c:930
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:978

References a, ao2_cleanup, ast_asprintf, ast_callid_strnprint(), ast_cdr_serialize_variables(), AST_CHAN_TP_INTERNAL, ast_channel_appl(), ast_channel_caller(), ast_channel_callgroup(), ast_channel_callid(), ast_channel_connected(), ast_channel_connected_effective_id(), ast_channel_context(), ast_channel_creationtime(), ast_channel_data(), ast_channel_dialed(), ast_channel_exten(), ast_channel_get_bridge(), ast_channel_get_by_name(), ast_channel_get_stream_topology(), ast_channel_language(), ast_channel_linkedid(), ast_channel_lock, ast_channel_name(), ast_channel_nativeformats(), ast_channel_pickupgroup(), ast_channel_priority(), ast_channel_readformat(), ast_channel_readtrans(), ast_channel_tech(), ast_channel_tenantid(), ast_channel_uniqueid(), ast_channel_unlock, ast_channel_unref, ast_channel_varshead(), ast_channel_whentohangup(), ast_channel_writeformat(), ast_channel_writetrans(), ast_cli(), ast_codec_media_type2str(), ast_complete_channels(), ast_format_cap_get_names(), AST_FORMAT_CAP_NAMES_LEN, ast_format_get_name(), ast_free, AST_LIST_TRAVERSE, ast_state2str(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_strlen(), ast_str_thread_get(), ast_stream_get_formats(), ast_stream_get_group(), ast_stream_get_metadata_list(), ast_stream_get_name(), ast_stream_get_state(), ast_stream_get_type(), ast_stream_state2str(), ast_stream_topology_get_count(), ast_stream_topology_get_stream(), ast_strlen_zero(), ast_translate_path_to_str(), ast_tvnow(), ast_tvzero(), ast_var_name(), ast_var_value(), ast_variables_destroy(), ast_bridge::callid, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, min, name, ast_variable::name, ast_variable::next, NULL, RAII_VAR, S_COR, S_OR, type, ast_bridge::uniqueid, ast_cli_entry::usage, ast_variable::value, and var.

◆ handle_showuptime()

static char * handle_showuptime ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 975 of file main/cli.c.

976{
977 struct timeval curtime = ast_tvnow();
978 int printsec;
979
980 switch (cmd) {
981 case CLI_INIT:
982 e->command = "core show uptime [seconds]";
983 e->usage =
984 "Usage: core show uptime [seconds]\n"
985 " Shows Asterisk uptime information.\n"
986 " The seconds word returns the uptime in seconds only.\n";
987 return NULL;
988
989 case CLI_GENERATE:
990 return NULL;
991 }
992 /* regular handler */
993 if (a->argc == e->args && !strcasecmp(a->argv[e->args-1],"seconds"))
994 printsec = 1;
995 else if (a->argc == e->args-1)
996 printsec = 0;
997 else
998 return CLI_SHOWUSAGE;
999 if (ast_startuptime.tv_sec) {
1000 print_uptimestr(a->fd, ast_tvsub(curtime, ast_startuptime), "System uptime: ", printsec);
1001 }
1002 if (ast_lastreloadtime.tv_sec) {
1003 print_uptimestr(a->fd, ast_tvsub(curtime, ast_lastreloadtime), "Last reload: ", printsec);
1004 }
1005 return CLI_SUCCESS;
1006}
struct timeval ast_lastreloadtime
Definition: asterisk.c:344

References a, ast_cli_entry::args, ast_lastreloadtime, ast_startuptime, ast_tvnow(), ast_tvsub(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, print_uptimestr(), and ast_cli_entry::usage.

◆ handle_softhangup()

static char * handle_softhangup ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1230 of file main/cli.c.

1231{
1232 struct ast_channel *c = NULL;
1233 static const char * const completions[] = { "all", NULL };
1234 char *complete;
1235
1236 switch (cmd) {
1237 case CLI_INIT:
1238 e->command = "channel request hangup";
1239 e->usage =
1240 "Usage: channel request hangup <channel>|<all>\n"
1241 " Request that a channel be hung up. The hangup takes effect\n"
1242 " the next time the driver reads or writes from the channel.\n"
1243 " If 'all' is specified instead of a channel name, all channels\n"
1244 " will see the hangup request.\n";
1245 return NULL;
1246 case CLI_GENERATE:
1247 if (a->pos != e->args) {
1248 return NULL;
1249 }
1250 complete = ast_cli_complete(a->word, completions, a->n);
1251 if (!complete) {
1252 complete = ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
1253 }
1254 return complete;
1255 }
1256
1257 if (a->argc != 4) {
1258 return CLI_SHOWUSAGE;
1259 }
1260
1261 if (!strcasecmp(a->argv[3], "all")) {
1262 struct ast_channel_iterator *iter = NULL;
1263 if (!(iter = ast_channel_iterator_all_new())) {
1264 return CLI_FAILURE;
1265 }
1266 for (; iter && (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
1268 ast_cli(a->fd, "Requested Hangup on channel '%s'\n", ast_channel_name(c));
1271 }
1273 } else if ((c = ast_channel_get_by_name(a->argv[3]))) {
1275 ast_cli(a->fd, "Requested Hangup on channel '%s'\n", ast_channel_name(c));
1279 } else {
1280 ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
1281 }
1282
1283 return CLI_SUCCESS;
1284}
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition: channel.c:1330
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition: channel.c:1369
@ AST_SOFTHANGUP_EXPLICIT
Definition: channel.h:1168
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2441
struct ast_channel_iterator * ast_channel_iterator_all_new(void)
Create a new channel iterator.
Definition: channel.c:1361

References a, ast_cli_entry::args, ast_channel_get_by_name(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_cli(), ast_cli_complete(), ast_complete_channels(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, c, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ handle_trace()

static char * handle_trace ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 630 of file main/cli.c.

631{
632 int atleast = 0;
633 const char *argv3 = a->argv ? S_OR(a->argv[3], "") : "";
634
635 switch (cmd) {
636 case CLI_INIT:
637 e->command = "core set trace";
638 e->usage =
639 "Usage: core set trace [atleast] <level> [module]\n"
640 " core set trace off\n"
641 "\n"
642 " Sets level of trace messages to be displayed or\n"
643 " sets a module name to display trace messages from.\n"
644 " 0 or off means no messages should be displayed.\n";
645 return NULL;
646
647 case CLI_GENERATE:
648 if (!strcasecmp(argv3, "atleast")) {
649 atleast = 1;
650 }
651 if (a->pos == 3 || (a->pos == 4 && atleast)) {
652 const char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], "");
653 int numbermatch = (ast_strlen_zero(pos) || strchr("123456789", pos[0])) ? 0 : 21;
654
655 if (a->n < 21 && numbermatch == 0) {
656 return complete_number(pos, 0, 0x7fffffff, a->n);
657 } else if (pos[0] == '0') {
658 if (a->n == 0) {
659 return ast_strdup("0");
660 }
661 } else if (a->n == (21 - numbermatch)) {
662 if (a->pos == 3 && !strncasecmp(argv3, "off", strlen(argv3))) {
663 return ast_strdup("off");
664 } else if (a->pos == 3 && !strncasecmp(argv3, "atleast", strlen(argv3))) {
665 return ast_strdup("atleast");
666 }
667 } else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) {
668 return ast_strdup("atleast");
669 }
670 } else if ((a->pos == 4 && !atleast && strcasecmp(argv3, "off") && strcasecmp(argv3, "channel"))
671 || (a->pos == 5 && atleast)) {
672 return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_RUNNING);
673 }
674 return NULL;
675 }
676 /* all the above return, so we proceed with the handler.
677 * we are guaranteed to be called with argc >= e->args;
678 */
679
680 return handle_debug_or_trace(TRACE_HANDLER, e, cmd, a);
681}
#define TRACE_HANDLER
Definition: main/cli.c:404

References a, ast_module_helper(), AST_MODULE_HELPER_RUNNING, ast_strdup, ast_strlen_zero(), CLI_GENERATE, CLI_INIT, ast_cli_entry::command, complete_number(), handle_debug_or_trace(), NULL, S_OR, TRACE_HANDLER, and ast_cli_entry::usage.

◆ handle_unload()

static char * handle_unload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 845 of file main/cli.c.

846{
847 /* "module unload mod_1 [mod_2 .. mod_N]" */
848 int x;
849 int force = AST_FORCE_SOFT;
850 const char *s;
851
852 switch (cmd) {
853 case CLI_INIT:
854 e->command = "module unload";
855 e->usage =
856 "Usage: module unload [-f|-h] <module_1> [<module_2> ... ]\n"
857 " Unloads the specified module from Asterisk. The -f\n"
858 " option causes the module to be unloaded even if it is\n"
859 " in use (may cause a crash) and the -h module causes the\n"
860 " module to be unloaded even if the module says it cannot, \n"
861 " which almost always will cause a crash.\n";
862 return NULL;
863
864 case CLI_GENERATE:
865 return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_UNLOAD);
866 }
867 if (a->argc < e->args + 1)
868 return CLI_SHOWUSAGE;
869 x = e->args; /* first argument */
870 s = a->argv[x];
871 if (s[0] == '-') {
872 if (s[1] == 'f')
873 force = AST_FORCE_FIRM;
874 else if (s[1] == 'h')
875 force = AST_FORCE_HARD;
876 else
877 return CLI_SHOWUSAGE;
878 if (a->argc < e->args + 2) /* need at least one module name */
879 return CLI_SHOWUSAGE;
880 x++; /* skip this argument */
881 }
882
883 for (; x < a->argc; x++) {
884 if (ast_unload_resource(a->argv[x], force)) {
885 ast_cli(a->fd, "Unable to unload resource %s\n", a->argv[x]);
886 return CLI_FAILURE;
887 }
888 ast_cli(a->fd, "Unloaded %s\n", a->argv[x]);
889 }
890
891 return CLI_SUCCESS;
892}
int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode)
Unload a module.
Definition: loader.c:1457
@ AST_FORCE_HARD
Definition: module.h:64
@ AST_FORCE_FIRM
Definition: module.h:63

References a, ast_cli_entry::args, ast_cli(), AST_FORCE_FIRM, AST_FORCE_HARD, AST_FORCE_SOFT, ast_module_helper(), AST_MODULE_HELPER_UNLOAD, ast_unload_resource(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

◆ handle_verbose()

static char * handle_verbose ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 683 of file main/cli.c.

684{
685 int oldval;
686 int newlevel;
687 int atleast = 0;
688 int silent = 0;
689 const char *argv3 = a->argv ? S_OR(a->argv[3], "") : "";
690
691 switch (cmd) {
692 case CLI_INIT:
693 e->command = "core set verbose";
694 e->usage =
695 "Usage: core set verbose [atleast] <level> [silent]\n"
696 " core set verbose off\n"
697 "\n"
698 " Sets level of verbose messages to be displayed.\n"
699 " 0 or off means no verbose messages should be displayed.\n"
700 " The silent option means the command does not report what\n"
701 " happened to the verbose level.\n"
702 " Equivalent to -v[v[...]] on startup\n";
703 return NULL;
704
705 case CLI_GENERATE:
706 if (!strcasecmp(argv3, "atleast")) {
707 atleast = 1;
708 }
709 if (a->pos == 3 || (a->pos == 4 && atleast)) {
710 const char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], "");
711 int numbermatch = (ast_strlen_zero(pos) || strchr("123456789", pos[0])) ? 0 : 21;
712
713 if (a->n < 21 && numbermatch == 0) {
714 return complete_number(pos, 0, 0x7fffffff, a->n);
715 } else if (pos[0] == '0') {
716 if (a->n == 0) {
717 return ast_strdup("0");
718 }
719 } else if (a->n == (21 - numbermatch)) {
720 if (a->pos == 3 && !strncasecmp(argv3, "off", strlen(argv3))) {
721 return ast_strdup("off");
722 } else if (a->pos == 3 && !strncasecmp(argv3, "atleast", strlen(argv3))) {
723 return ast_strdup("atleast");
724 }
725 } else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) {
726 return ast_strdup("atleast");
727 }
728 } else if ((a->pos == 4 && !atleast && strcasecmp(argv3, "off"))
729 || (a->pos == 5 && atleast)) {
730 const char *pos = S_OR(a->argv[a->pos], "");
731
732 if (a->n == 0 && !strncasecmp(pos, "silent", strlen(pos))) {
733 return ast_strdup("silent");
734 }
735 }
736 return NULL;
737 }
738 /* all the above return, so we proceed with the handler.
739 * we are guaranteed to be called with argc >= e->args;
740 */
741
742 if (a->argc <= e->args) {
743 return CLI_SHOWUSAGE;
744 }
745
746 if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args], "off")) {
747 newlevel = 0;
748 } else {
749 if (!strcasecmp(a->argv[e->args], "atleast")) {
750 atleast = 1;
751 }
752 if (a->argc == e->args + atleast + 2
753 && !strcasecmp(a->argv[e->args + atleast + 1], "silent")) {
754 silent = 1;
755 }
756 if (a->argc != e->args + atleast + silent + 1) {
757 return CLI_SHOWUSAGE;
758 }
759 if (sscanf(a->argv[e->args + atleast], "%30d", &newlevel) != 1) {
760 return CLI_SHOWUSAGE;
761 }
762 }
763
764 /* Update verbose level */
765 oldval = ast_verb_console_get();
766 if (!atleast || newlevel > oldval) {
767 ast_verb_console_set(newlevel);
768 } else {
769 newlevel = oldval;
770 }
771
772 if (silent) {
773 /* Be silent after setting the level. */
774 return CLI_SUCCESS;
775 }
776
777 /* Report verbose level status */
778 status_debug_verbose(a, VERBOSE_HANDLER, oldval, newlevel);
779
780 return CLI_SUCCESS;
781}
int ast_verb_console_get(void)
Get this thread's console verbosity level.
Definition: logger.c:2643
void ast_verb_console_set(int verb_level)
Set this thread's console verbosity level.
Definition: logger.c:2661
#define VERBOSE_HANDLER
Definition: main/cli.c:405

References a, ast_cli_entry::args, ast_strdup, ast_strlen_zero(), ast_verb_console_get(), ast_verb_console_set(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_number(), NULL, S_OR, status_debug_verbose(), ast_cli_entry::usage, and VERBOSE_HANDLER.

◆ help1()

static char * help1 ( int  fd,
const char *const  match[],
int  locked 
)
static

helper for final part of handle_help if locked = 1, assume the list is already locked

Definition at line 2533 of file main/cli.c.

2534{
2535 char matchstr[80] = "";
2536 struct ast_cli_entry *e = NULL;
2537 int len = 0;
2538 int found = 0;
2539
2540 if (match) {
2541 ast_join(matchstr, sizeof(matchstr), match);
2542 len = strlen(matchstr);
2543 }
2544 if (!locked)
2546 while ( (e = cli_next(e)) ) {
2547 /* Hide commands that start with '_' */
2548 if (e->_full_cmd[0] == '_')
2549 continue;
2550 if (match && strncasecmp(matchstr, e->_full_cmd, len))
2551 continue;
2552 ast_cli(fd, "%-30s -- %s\n", e->_full_cmd,
2553 S_OR(e->summary, "<no description available>"));
2554 found++;
2555 }
2556 if (!locked)
2558 if (!found && matchstr[0])
2559 ast_cli(fd, "No such command '%s'.\n", matchstr);
2560 return CLI_SUCCESS;
2561}
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2388

References ast_cli_entry::_full_cmd, ast_cli(), ast_join, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, cli_next(), CLI_SUCCESS, len(), match(), NULL, S_OR, and ast_cli_entry::summary.

Referenced by handle_help().

◆ is_prefix()

static char * is_prefix ( const char *  word,
const char *  token,
int  pos,
int *  actual 
)
static

if word is a valid prefix for token, returns the pos-th match as a malloced string, or NULL otherwise. Always tell in *actual how many matches we got.

Definition at line 2277 of file main/cli.c.

2279{
2280 int lw;
2281 char *s, *t1;
2282
2283 *actual = 0;
2284 if (ast_strlen_zero(token))
2285 return NULL;
2286 if (ast_strlen_zero(word))
2287 word = ""; /* dummy */
2288 lw = strlen(word);
2289 if (strcspn(word, cli_rsvd) != lw)
2290 return NULL; /* no match if word has reserved chars */
2291 if (strchr(cli_rsvd, token[0]) == NULL) { /* regular match */
2292 if (strncasecmp(token, word, lw)) /* no match */
2293 return NULL;
2294 *actual = 1;
2295 return (pos != 0) ? NULL : ast_strdup(token);
2296 }
2297 /* now handle regexp match */
2298
2299 /* Wildcard always matches, so we never do is_prefix on them */
2300
2301 t1 = ast_strdupa(token + 1); /* copy, skipping first char */
2302 while (pos >= 0 && (s = strsep(&t1, cli_rsvd)) && *s) {
2303 if (*s == '%') /* wildcard */
2304 continue;
2305 if (strncasecmp(s, word, lw)) /* no match */
2306 continue;
2307 (*actual)++;
2308 if (pos-- == 0)
2309 return ast_strdup(s);
2310 }
2311 return NULL;
2312}
char * strsep(char **str, const char *delims)
static const char cli_rsvd[]
Definition: main/cli.c:2040

References ast_strdup, ast_strdupa, ast_strlen_zero(), cli_rsvd, NULL, and strsep().

Referenced by __ast_cli_generator().

◆ modlist_modentry()

static int modlist_modentry ( const char *  module,
const char *  description,
int  usecnt,
const char *  status,
const char *  like,
enum ast_module_support_level  support_level 
)
static

Definition at line 900 of file main/cli.c.

903{
904 /* Comparing the like with the module */
905 if (strcasestr(module, like) ) {
906 ast_cli(climodentryfd, MODLIST_FORMAT, module, description, usecnt,
908 return 1;
909 }
910 return 0;
911}
jack_status_t status
Definition: app_jack.c:149
char * strcasestr(const char *, const char *)
static int usecnt
Definition: chan_ooh323.c:332
#define MODLIST_FORMAT
Definition: main/cli.c:894
const char * ast_module_support_level_to_string(enum ast_module_support_level support_level)
Definition: loader.c:2934

References ast_cli(), ast_module_support_level_to_string(), climodentryfd, MODLIST_FORMAT, status, strcasestr(), and usecnt.

Referenced by handle_modlist().

◆ more_words()

static int more_words ( const char *const *  dst)
static

returns true if there are more words to match

Definition at line 2827 of file main/cli.c.

2828{
2829 int i;
2830 for (i = 0; dst[i]; i++) {
2831 if (dst[i][0] != '[')
2832 return -1;
2833 }
2834 return 0;
2835}

Referenced by __ast_cli_generator().

◆ parse_args()

static char * parse_args ( const char *  s,
int *  argc,
const char *  argv[],
int  max,
int *  trailingwhitespace 
)
static

Definition at line 2609 of file main/cli.c.

2610{
2611 char *duplicate, *cur;
2612 int x = 0;
2613 int quoted = 0;
2614 int escaped = 0;
2615 int whitespace = 1;
2616 int dummy = 0;
2617
2618 if (trailingwhitespace == NULL)
2619 trailingwhitespace = &dummy;
2620 *trailingwhitespace = 0;
2621 if (s == NULL) /* invalid, though! */
2622 return NULL;
2623 /* make a copy to store the parsed string */
2624 if (!(duplicate = ast_strdup(s)))
2625 return NULL;
2626
2627 cur = duplicate;
2628
2629 /* Remove leading spaces from the command */
2630 while (isspace(*s)) {
2631 cur++;
2632 s++;
2633 }
2634
2635 /* scan the original string copying into cur when needed */
2636 for (; *s ; s++) {
2637 if (x >= max - 1) {
2638 ast_log(LOG_WARNING, "Too many arguments, truncating at %s\n", s);
2639 break;
2640 }
2641 if (*s == '"' && !escaped) {
2642 quoted = !quoted;
2643 if (quoted && whitespace) {
2644 /* start a quoted string from previous whitespace: new argument */
2645 argv[x++] = cur;
2646 whitespace = 0;
2647 }
2648 } else if ((*s == ' ' || *s == '\t') && !(quoted || escaped)) {
2649 /* If we are not already in whitespace, and not in a quoted string or
2650 processing an escape sequence, and just entered whitespace, then
2651 finalize the previous argument and remember that we are in whitespace
2652 */
2653 if (!whitespace) {
2654 *cur++ = '\0';
2655 whitespace = 1;
2656 }
2657 } else if (*s == '\\' && !escaped) {
2658 escaped = 1;
2659 } else {
2660 if (whitespace) {
2661 /* we leave whitespace, and are not quoted. So it's a new argument */
2662 argv[x++] = cur;
2663 whitespace = 0;
2664 }
2665 *cur++ = *s;
2666 escaped = 0;
2667 }
2668 }
2669 /* Null terminate */
2670 *cur++ = '\0';
2671 /* XXX put a NULL in the last argument, because some functions that take
2672 * the array may want a null-terminated array.
2673 * argc still reflects the number of non-NULL entries.
2674 */
2675 argv[x] = NULL;
2676 *argc = x;
2677 *trailingwhitespace = whitespace;
2678 return duplicate;
2679}
static void dummy(char *unused,...)
Definition: chan_unistim.c:220

References ast_log, ast_strdup, dummy(), LOG_WARNING, max, and NULL.

Referenced by __ast_cli_generator(), and ast_cli_command_full().

◆ print_uptimestr()

static void print_uptimestr ( int  fd,
struct timeval  timeval,
const char *  prefix,
int  printsec 
)
static

Definition at line 913 of file main/cli.c.

914{
915 int x; /* the main part - years, weeks, etc. */
916 struct ast_str *out;
917
918#define SECOND (1)
919#define MINUTE (SECOND*60)
920#define HOUR (MINUTE*60)
921#define DAY (HOUR*24)
922#define WEEK (DAY*7)
923#define YEAR (DAY*365)
924#define NEEDCOMMA(x) ((x) ? ", " : "") /* define if we need a comma */
925 if (timeval.tv_sec < 0) /* invalid, nothing to show */
926 return;
927
928 if (printsec) { /* plain seconds output */
929 ast_cli(fd, "%s%lu\n", prefix, (u_long)timeval.tv_sec);
930 return;
931 }
932 out = ast_str_alloca(256);
933 if (timeval.tv_sec > YEAR) {
934 x = (timeval.tv_sec / YEAR);
935 timeval.tv_sec -= (x * YEAR);
936 ast_str_append(&out, 0, "%d year%s%s", x, ESS(x), NEEDCOMMA(timeval.tv_sec));
937 }
938 if (timeval.tv_sec > WEEK) {
939 x = (timeval.tv_sec / WEEK);
940 timeval.tv_sec -= (x * WEEK);
941 ast_str_append(&out, 0, "%d week%s%s", x, ESS(x), NEEDCOMMA(timeval.tv_sec));
942 }
943 if (timeval.tv_sec > DAY) {
944 x = (timeval.tv_sec / DAY);
945 timeval.tv_sec -= (x * DAY);
946 ast_str_append(&out, 0, "%d day%s%s", x, ESS(x), NEEDCOMMA(timeval.tv_sec));
947 }
948 if (timeval.tv_sec > HOUR) {
949 x = (timeval.tv_sec / HOUR);
950 timeval.tv_sec -= (x * HOUR);
951 ast_str_append(&out, 0, "%d hour%s%s", x, ESS(x), NEEDCOMMA(timeval.tv_sec));
952 }
953 if (timeval.tv_sec > MINUTE) {
954 x = (timeval.tv_sec / MINUTE);
955 timeval.tv_sec -= (x * MINUTE);
956 ast_str_append(&out, 0, "%d minute%s%s", x, ESS(x), NEEDCOMMA(timeval.tv_sec));
957 }
958 x = timeval.tv_sec;
959 if (x > 0 || ast_str_strlen(out) == 0) {
960 /* if there is nothing, print 0 seconds */
961 ast_str_append(&out, 0, "%d second%s", x, ESS(x));
962 }
963 ast_cli(fd, "%s%s\n", prefix, ast_str_buffer(out));
964}
#define HOUR
#define WEEK
#define DAY
#define YEAR
#define NEEDCOMMA(x)
#define MINUTE
FILE * out
Definition: utils/frame.c:33

References ast_cli(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_strlen(), DAY, ESS, HOUR, MINUTE, NEEDCOMMA, out, prefix, WEEK, and YEAR.

Referenced by ast_cli_print_timestr_fromseconds(), handle_showcalls(), and handle_showuptime().

◆ remove_shutdown_command()

static void remove_shutdown_command ( struct ast_cli_entry e)
static

Definition at line 2401 of file main/cli.c.

2402{
2406}
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
Definition: vector.h:582
#define AST_VECTOR_REMOVE_ELEM_UNORDERED(vec, elem, cleanup)
Remove an element from a vector.
Definition: vector.h:594

References ast_rwlock_unlock, ast_rwlock_wrlock, AST_VECTOR_ELEM_CLEANUP_NOOP, AST_VECTOR_REMOVE_ELEM_UNORDERED, shutdown_commands, and shutdown_commands_lock.

Referenced by ast_cli_unregister().

◆ set_full_cmd()

static int set_full_cmd ( struct ast_cli_entry e)
static

initialize the _full_cmd string and related parameters, return 0 on success, -1 on error.

Definition at line 2046 of file main/cli.c.

2047{
2048 int i;
2049 char buf[80];
2050
2051 ast_join(buf, sizeof(buf), e->cmda);
2052 e->_full_cmd = ast_strdup(buf);
2053 if (!e->_full_cmd) {
2054 ast_log(LOG_WARNING, "-- cannot allocate <%s>\n", buf);
2055 return -1;
2056 }
2057 e->cmdlen = strcspn(e->_full_cmd, cli_rsvd);
2058 for (i = 0; e->cmda[i]; i++)
2059 ;
2060 e->args = i;
2061 return 0;
2062}

References ast_cli_entry::_full_cmd, ast_cli_entry::args, ast_join, ast_log, ast_strdup, buf, cli_rsvd, ast_cli_entry::cmda, ast_cli_entry::cmdlen, and LOG_WARNING.

Referenced by __ast_cli_register().

◆ status_debug_verbose()

static void status_debug_verbose ( struct ast_cli_args a,
int  handler,
int  old_val,
int  cur_val 
)
static

Definition at line 407 of file main/cli.c.

408{
409 char was_buf[30];
410 const char *was;
411 const char *what = "";
412
413 switch(handler) {
414 case DEBUG_HANDLER:
415 what = "Core debug";
416 break;
417 case TRACE_HANDLER:
418 what = "Core trace";
419 break;
420 case VERBOSE_HANDLER:
421 what = "Console verbose";
422 break;
423 }
424
425 if (old_val) {
426 snprintf(was_buf, sizeof(was_buf), "%d", old_val);
427 was = was_buf;
428 } else {
429 was = "OFF";
430 }
431
432 if (old_val == cur_val) {
433 ast_cli(a->fd, "%s is still %s.\n", what, was);
434 } else {
435 char now_buf[30];
436 const char *now;
437
438 if (cur_val) {
439 snprintf(now_buf, sizeof(now_buf), "%d", cur_val);
440 now = now_buf;
441 } else {
442 now = "OFF";
443 }
444
445 ast_cli(a->fd, "%s was %s and is now %s.\n", what, was, now);
446 }
447}

References a, ast_cli(), DEBUG_HANDLER, handler(), TRACE_HANDLER, and VERBOSE_HANDLER.

Referenced by handle_debug_or_trace(), and handle_verbose().

◆ word_match()

static int word_match ( const char *  cmd,
const char *  cli_word 
)
static

match a word in the CLI entry. returns -1 on mismatch, 0 on match of an optional word, 1 on match of a full word.

The pattern can be any_word match for equal [foo|bar|baz] optionally, one of these words {foo|bar|baz} exactly, one of these words % any word

Definition at line 2238 of file main/cli.c.

2239{
2240 int l;
2241 char *pos;
2242
2243 if (ast_strlen_zero(cmd) || ast_strlen_zero(cli_word))
2244 return -1;
2245 if (!strchr(cli_rsvd, cli_word[0])) /* normal match */
2246 return (strcasecmp(cmd, cli_word) == 0) ? 1 : -1;
2247 l = strlen(cmd);
2248 /* wildcard match - will extend in the future */
2249 if (l > 0 && cli_word[0] == '%') {
2250 return 1; /* wildcard */
2251 }
2252
2253 /* Start a search for the command entered against the cli word in question */
2254 pos = strcasestr(cli_word, cmd);
2255 while (pos) {
2256
2257 /*
2258 *Check if the word matched with is surrounded by reserved characters on both sides
2259 * and isn't at the beginning of the cli_word since that would make it check in a location we shouldn't know about.
2260 * If it is surrounded by reserved chars and isn't at the beginning, it's a match.
2261 */
2262 if (pos != cli_word && strchr(cli_rsvd, pos[-1]) && strchr(cli_rsvd, pos[l])) {
2263 return 1; /* valid match */
2264 }
2265
2266 /* Ok, that one didn't match, strcasestr to the next appearance of the command and start over.*/
2267 pos = strcasestr(pos + 1, cmd);
2268 }
2269 /* If no matches were found over the course of the while loop, we hit the end of the string. It's a mismatch. */
2270 return -1;
2271}

References ast_strlen_zero(), cli_rsvd, and strcasestr().

Referenced by __ast_cli_generator(), and find_cli().

Variable Documentation

◆ ast_cli_buf

struct ast_threadstorage ast_cli_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_ast_cli_buf , .custom_init = NULL , }
static

Definition at line 110 of file main/cli.c.

Referenced by ast_cli().

◆ cli_channels_cli

struct ast_cli_entry cli_channels_cli[]
static

Definition at line 2028 of file main/cli.c.

Referenced by ast_cli_channels_init(), and cli_channels_shutdown().

◆ cli_cli

struct ast_cli_entry cli_cli[]
static

Definition at line 1996 of file main/cli.c.

Referenced by ast_builtins_init(), and cli_shutdown().

◆ cli_default_perm

int cli_default_perm = 1
static

Default permissions value 1=Permit 0=Deny.

Definition at line 87 of file main/cli.c.

Referenced by ast_cli_perms_init(), and cli_has_permissions().

◆ cli_perms

struct cli_perms cli_perms = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

◆ cli_rsvd

const char cli_rsvd[] = "[]{}|*%"
static

Some regexp characters in cli arguments are reserved and used as separators.

Definition at line 2040 of file main/cli.c.

Referenced by is_prefix(), set_full_cmd(), and word_match().

◆ climodentryfd

int climodentryfd = -1
static

Definition at line 898 of file main/cli.c.

Referenced by handle_modlist(), and modlist_modentry().

◆ climodentrylock

ast_mutex_t climodentrylock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 897 of file main/cli.c.

Referenced by handle_modlist().

◆ current

size_t current

Definition at line 113 of file main/cli.c.

◆ debug_modules

struct module_level_list debug_modules = AST_RWLIST_HEAD_INIT_VALUE
static

lists of module names and their debug/trace levels

Definition at line 107 of file main/cli.c.

Referenced by ast_debug_get_by_module(), and handle_debug_or_trace().

◆ elems

struct ast_cli_entry* * elems

Definition at line 113 of file main/cli.c.

◆ helpers

struct helpers helpers = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

◆ max

size_t max

Definition at line 113 of file main/cli.c.

Referenced by complete_number(), and parse_args().

◆ perms_config

const char perms_config[] = "cli_permissions.conf"
static

CLI permissions config file.

Definition at line 85 of file main/cli.c.

Referenced by ast_cli_perms_init().

◆ permsconfiglock

ast_mutex_t permsconfiglock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

mutex used to prevent a user from running the 'cli reload permissions' command while it is already running.

Definition at line 91 of file main/cli.c.

Referenced by ast_cli_perms_init().

◆ 

struct { ... } shutdown_commands

◆ shutdown_commands_lock

ast_rwlock_t shutdown_commands_lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} }
static

◆ trace_modules

struct module_level_list trace_modules = AST_RWLIST_HEAD_INIT_VALUE
static

Definition at line 108 of file main/cli.c.

Referenced by ast_trace_get_by_module(), and handle_debug_or_trace().