Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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_nodebugchan_deprecated (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 889 of file main/cli.c.

◆ MODLIST_FORMAT2

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

Definition at line 890 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 2859 of file main/cli.c.

2860{
2861 const char *argv[AST_MAX_ARGS];
2862 struct ast_cli_entry *e = NULL;
2863 int x = 0, argindex, matchlen;
2864 int matchnum=0;
2865 char *ret = NULL;
2866 char matchstr[80] = "";
2867 int tws = 0;
2868 /* Split the argument into an array of words */
2869 char *duplicate = parse_args(text, &x, argv, ARRAY_LEN(argv), &tws);
2870
2871 if (!duplicate) /* malloc error */
2872 return NULL;
2873
2874 /* Compute the index of the last argument (could be an empty string) */
2875 argindex = (!ast_strlen_zero(word) && x>0) ? x-1 : x;
2876
2877 /* rebuild the command, ignore terminating white space and flatten space */
2878 ast_join(matchstr, sizeof(matchstr)-1, argv);
2879 matchlen = strlen(matchstr);
2880 if (tws) {
2881 strcat(matchstr, " "); /* XXX */
2882 if (matchlen)
2883 matchlen++;
2884 }
2885 if (lock)
2887 while ( (e = cli_next(e)) ) {
2888 /* XXX repeated code */
2889 int src = 0, dst = 0, n = 0;
2890
2891 if (e->command[0] == '_')
2892 continue;
2893
2894 /*
2895 * Try to match words, up to and excluding the last word, which
2896 * is either a blank or something that we want to extend.
2897 */
2898 for (;src < argindex; dst++, src += n) {
2899 n = word_match(argv[src], e->cmda[dst]);
2900 if (n < 0)
2901 break;
2902 }
2903
2904 if (src != argindex && more_words(e->cmda + dst)) /* not a match */
2905 continue;
2906 ret = is_prefix(argv[src], e->cmda[dst], state - matchnum, &n);
2907 matchnum += n; /* this many matches here */
2908 if (ret) {
2909 /*
2910 * argv[src] is a valid prefix of the next word in this
2911 * command. If this is also the correct entry, return it.
2912 */
2913 if (matchnum > state)
2914 break;
2915 ast_free(ret);
2916 ret = NULL;
2917 } else if (ast_strlen_zero(e->cmda[dst])) {
2918 /*
2919 * This entry is a prefix of the command string entered
2920 * (only one entry in the list should have this property).
2921 * Run the generator if one is available. In any case we are done.
2922 */
2923 if (e->handler) { /* new style command */
2924 struct ast_cli_args a = {
2925 .line = matchstr, .word = word,
2926 .pos = argindex,
2927 .n = state - matchnum,
2928 .argv = argv,
2929 .argc = x};
2930
2931 /* If the command is in a module it must be running. */
2932 if (!e->module || ast_module_running_ref(e->module)) {
2933 ret = e->handler(e, CLI_GENERATE, &a);
2935 }
2936 }
2937 if (ret)
2938 break;
2939 }
2940 }
2941 if (lock)
2943 ast_free(duplicate);
2944 return ret;
2945}
char * text
Definition: app_queue.c:1639
ast_mutex_t lock
Definition: app_sla.c:331
#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:2257
static int more_words(const char *const *dst)
returns true if there are more words to match
Definition: main/cli.c:2846
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:2296
static struct ast_cli_entry * cli_next(struct ast_cli_entry *e)
Definition: main/cli.c:961
static char * parse_args(const char *s, int *argc, const char *argv[], int max, int *trailingwhitespace)
Definition: main/cli.c:2628
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition: module.h:455
#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:666

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 2450 of file main/cli.c.

2451{
2452 struct ast_cli_entry *cur;
2453 int i, lf, ret = -1;
2454
2455 struct ast_cli_args a; /* fake argument */
2456 char **dst = (char **)e->cmda; /* need to cast as the entry is readonly */
2457 char *s;
2458
2460
2461 if (cli_is_registered(e)) {
2462 ast_log(LOG_WARNING, "Command '%s' already registered (the same ast_cli_entry)\n",
2463 S_OR(e->_full_cmd, e->command));
2464 ret = 0; /* report success */
2465 goto done;
2466 }
2467
2468 memset(&a, '\0', sizeof(a));
2469
2470 e->module = module;
2471 /* No module reference needed here, the module called us. */
2472 e->handler(e, CLI_INIT, &a);
2473
2474 /* XXX check that usage and command are filled up */
2475 s = ast_skip_blanks(e->command);
2476 s = e->command = ast_strdup(s);
2477 for (i=0; !ast_strlen_zero(s) && i < AST_MAX_CMD_LEN-1; i++) {
2478 *dst++ = s; /* store string */
2479 s = ast_skip_nonblanks(s);
2480 if (*s == '\0') /* we are done */
2481 break;
2482 *s++ = '\0';
2483 s = ast_skip_blanks(s);
2484 }
2485 *dst++ = NULL;
2486
2487 if (find_cli(e->cmda, 1)) {
2488 ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n",
2489 S_OR(e->_full_cmd, e->command));
2490 goto done;
2491 }
2492 if (set_full_cmd(e)) {
2493 ast_log(LOG_WARNING, "Error registering CLI Command '%s'\n",
2494 S_OR(e->_full_cmd, e->command));
2495 goto done;
2496 }
2497
2498 lf = e->cmdlen;
2500 int len = cur->cmdlen;
2501 if (lf < len)
2502 len = lf;
2503 if (strncasecmp(e->_full_cmd, cur->_full_cmd, len) < 0) {
2505 break;
2506 }
2507 }
2509
2510 if (!cur)
2512 ret = 0; /* success */
2513
2514done:
2516 if (ret) {
2517 ast_free(e->command);
2518 e->command = NULL;
2519 }
2520
2521 return ret;
2522}
#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:2346
static int set_full_cmd(struct ast_cli_entry *e)
Definition: main/cli.c:2065
static int cli_is_registered(struct ast_cli_entry *e)
Definition: main/cli.c:2408
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 2527 of file main/cli.c.

2528{
2529 int i, res = 0;
2530
2531 for (i = 0; i < len; i++) {
2532 res |= __ast_cli_register(e + i, module);
2533 }
2534
2535 return res;
2536}
int __ast_cli_register(struct ast_cli_entry *e, struct ast_module *module)
Definition: main/cli.c:2450

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 2952 of file main/cli.c.

2953{
2954 int found = 0;
2955 int i;
2956
2958 for (i = 0; i < AST_VECTOR_SIZE(&shutdown_commands); ++i) {
2959 if (e == AST_VECTOR_GET(&shutdown_commands, i)) {
2960 found = 1;
2961 break;
2962 }
2963 }
2965
2966 return found;
2967}
#define ast_rwlock_rdlock(a)
Definition: lock.h:235
#define ast_rwlock_unlock(a)
Definition: lock.h:234
static ast_rwlock_t shutdown_commands_lock
Definition: main/cli.c:112
static struct @332 shutdown_commands
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680

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 2233 of file main/cli.c.

2234{
2238}
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:2222
static struct ast_cli_entry cli_cli[]
Definition: main/cli.c:2014
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113

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
@ AST_DYNSTR_BUILD_FAILED
Definition: strings.h:943
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
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:1771

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 3056 of file main/cli.c.

3057{
3058 int res;
3059
3063
3064 return res;
3065}
#define ast_rwlock_wrlock(a)
Definition: lock.h:236
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256

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 2240 of file main/cli.c.

2241{
2244}
static void cli_channels_shutdown(void)
Definition: main/cli.c:2227
static struct ast_cli_entry cli_channels_cli[]
Definition: main/cli.c:2046

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 2969 of file main/cli.c.

2970{
2971 const char *args[AST_MAX_ARGS + 1];
2972 struct ast_cli_entry *e = NULL;
2973 int x;
2974 char *duplicate = parse_args(s, &x, args + 1, AST_MAX_ARGS, NULL);
2975 char tmp[AST_MAX_ARGS + 1];
2976 char *retval = CLI_FAILURE;
2977 struct ast_cli_args a = {
2978 .fd = fd, .argc = x, .argv = args+1 };
2979
2980 if (duplicate == NULL)
2981 return RESULT_FAILURE;
2982
2983 if (x < 1) /* We need at least one entry, otherwise ignore */
2984 goto done;
2985
2987 e = find_cli(args + 1, 0);
2988 if (e)
2991 if (e == NULL) {
2992 ast_cli(fd, "No such command '%s' (type 'core show help %s' for other possible commands)\n", s, find_best(args + 1));
2993 goto done;
2994 }
2995
2997 ast_cli(fd, "Command '%s' cannot be run during shutdown\n", s);
2998 goto done;
2999 }
3000
3001 ast_join(tmp, sizeof(tmp), args + 1);
3002 /* Check if the user has rights to run this command. */
3003 if (!cli_has_permissions(uid, gid, tmp)) {
3004 ast_cli(fd, "You don't have permissions to run '%s' command\n", tmp);
3005 goto done;
3006 }
3007
3008 /*
3009 * Within the handler, argv[-1] contains a pointer to the ast_cli_entry.
3010 * Remember that the array returned by parse_args is NULL-terminated.
3011 */
3012 args[0] = (char *)e;
3013
3014 /* If the command is in a module it must be running. */
3015 if (!e->module || ast_module_running_ref(e->module)) {
3016 retval = e->handler(e, CLI_HANDLER, &a);
3018 }
3019
3020 if (retval == CLI_SHOWUSAGE) {
3021 ast_cli(fd, "%s", S_OR(e->usage, "Invalid usage, but no usage information available.\n"));
3022 } else if (retval == CLI_FAILURE) {
3023 ast_cli(fd, "Command '%s' failed.\n", s);
3024 }
3025
3026done:
3027 if (e) {
3029 }
3030 ast_free(duplicate);
3032}
int ast_shutting_down(void)
Definition: asterisk.c:1872
static int tmp()
Definition: bt_open.c:389
#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
static ENTRY retval
Definition: hsearch.c:50
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:757
static char * find_best(const char *argv[])
Definition: main/cli.c:2390
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:2952
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, retval, S_OR, tmp(), 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 3034 of file main/cli.c.

3035{
3036 char cmd[512];
3037 int x, y = 0, count = 0;
3038
3039 for (x = 0; x < size; x++) {
3040 cmd[y] = s[x];
3041 y++;
3042 if (s[x] == '\0') {
3043 ast_cli_command_full(uid, gid, fd, cmd);
3044 y = 0;
3045 count++;
3046 }
3047 }
3048 return count;
3049}
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:2969

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:1841

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

1842{
1843 int i, which = 0, len;
1844 len = ast_strlen_zero(word) ? 0 : strlen(word);
1845
1846 for (i = 0; choices[i]; i++) {
1847 if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state) {
1848 if (state != -1) {
1849 return ast_strdup(choices[i]);
1850 }
1851
1852 if (ast_cli_completion_add(ast_strdup(choices[i]))) {
1853 return NULL;
1854 }
1855 }
1856 }
1857 return NULL;
1858}
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2756

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_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 2756 of file main/cli.c.

2757{
2758 return cli_completion_vector_add(ast_threadstorage_get_ptr(&completion_storage), value);
2759}
static int cli_completion_vector_add(struct ast_vector_string *vec, char *value)
Definition: main/cli.c:2735
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(), ast_cli_complete(), ast_complete_applications(), ast_complete_channels(), category_complete(), cli_complete_endpoint(), cli_complete_show(), cli_complete_uri(), 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_show_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 2700 of file main/cli.c.

2701{
2703 char **match_list;
2704
2705 if (!vec) {
2706 return NULL;
2707 }
2708
2709 if (AST_VECTOR_APPEND(vec, NULL)) {
2710 /* We failed to NULL terminate the elements */
2713
2714 return NULL;
2715 }
2716
2717 match_list = AST_VECTOR_STEAL_ELEMENTS(vec);
2719
2720 return match_list;
2721}
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:2761
String vector definitions.
Definition: vector.h:55
#define AST_VECTOR_STEAL_ELEMENTS(vec)
Steal the elements from a vector and reinitialize.
Definition: vector.h:140
#define AST_VECTOR_PTR_FREE(vec)
Deallocates this vector pointer.
Definition: vector.h:189
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:862

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 2761 of file main/cli.c.

2762{
2763 char *retstr, *prevstr;
2764 size_t max_equal;
2765 size_t which = 0;
2766 struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec));
2767
2768 /* Recursion into this function is a coding error. */
2769 ast_assert(!ast_threadstorage_get_ptr(&completion_storage));
2770
2771 if (!vec) {
2772 return NULL;
2773 }
2774
2775 if (ast_threadstorage_set_ptr(&completion_storage, vec)) {
2776 ast_log(LOG_ERROR, "Failed to initialize threadstorage for completion.\n");
2777 ast_free(vec);
2778
2779 return NULL;
2780 }
2781
2782 while ((retstr = ast_cli_generator(text, word, which)) != NULL) {
2783 if (cli_completion_vector_add(vec, retstr)) {
2784 ast_threadstorage_set_ptr(&completion_storage, NULL);
2785
2786 goto vector_cleanup;
2787 }
2788
2789 ++which;
2790 }
2791
2792 ast_threadstorage_set_ptr(&completion_storage, NULL);
2793
2794 if (!AST_VECTOR_SIZE(vec)) {
2796
2797 return NULL;
2798 }
2799
2800 prevstr = AST_VECTOR_GET(vec, 0);
2801 max_equal = strlen(prevstr);
2802 which = 1;
2803
2804 /* Find the longest substring that is common to all results
2805 * (it is a candidate for completion), and store a copy in entry 0.
2806 */
2807 while (which < AST_VECTOR_SIZE(vec)) {
2808 size_t i = 0;
2809
2810 retstr = AST_VECTOR_GET(vec, which);
2811 /* Check for and remove duplicate strings. */
2812 if (!strcasecmp(prevstr, retstr)) {
2813 AST_VECTOR_REMOVE(vec, which, 1);
2814 ast_free(retstr);
2815
2816 continue;
2817 }
2818
2819 while (i < max_equal && toupper(prevstr[i]) == toupper(retstr[i])) {
2820 i++;
2821 }
2822
2823 max_equal = i;
2824 prevstr = retstr;
2825 ++which;
2826 }
2827
2828 /* Insert longest match to position 0. */
2829 retstr = ast_strndup(AST_VECTOR_GET(vec, 0), max_equal);
2830 if (!retstr || AST_VECTOR_INSERT_AT(vec, 0, retstr)) {
2831 ast_free(retstr);
2832
2833 goto vector_cleanup;
2834 }
2835
2836 return vec;
2837
2838vector_cleanup:
2841
2842 return NULL;
2843}
#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:2947
int ast_threadstorage_set_ptr(struct ast_threadstorage *ts, void *ptr)
Set a raw pointer from threadstorage.
#define ast_assert(a)
Definition: utils.h:739
#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:338
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
Definition: vector.h:412

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 2947 of file main/cli.c.

2948{
2949 return __ast_cli_generator(text, word, state, 1);
2950}
static char * __ast_cli_generator(const char *text, const char *word, int state, int lock)
Definition: main/cli.c:2859

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 2100 of file main/cli.c.

2101{
2102 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2103 struct ast_config *cfg;
2104 char *cat = NULL;
2105 struct ast_variable *v;
2106 struct usergroup_cli_perm *user_group, *cp_entry;
2107 struct cli_perm *perm = NULL;
2108 struct passwd *pw;
2109 struct group *gr;
2110
2112 ast_log(LOG_NOTICE, "You must wait until last 'cli reload permissions' command finish\n");
2113 return 1;
2114 }
2115
2116 cfg = ast_config_load2(perms_config, "" /* core, can't reload */, config_flags);
2117 if (!cfg) {
2119 return 1;
2120 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2122 return 0;
2123 }
2124
2125 /* free current structures. */
2127
2128 while ((cat = ast_category_browse(cfg, cat))) {
2129 if (!strcasecmp(cat, "general")) {
2130 /* General options */
2131 for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
2132 if (!strcasecmp(v->name, "default_perm")) {
2133 cli_default_perm = (!strcasecmp(v->value, "permit")) ? 1: 0;
2134 }
2135 }
2136 continue;
2137 }
2138
2139 /* users or groups */
2140 gr = NULL, pw = NULL;
2141 if (cat[0] == '@') {
2142 /* This is a group */
2143 gr = getgrnam(&cat[1]);
2144 if (!gr) {
2145 ast_log (LOG_WARNING, "Unknown group '%s'\n", &cat[1]);
2146 continue;
2147 }
2148 } else {
2149 /* This is a user */
2150 pw = getpwnam(cat);
2151 if (!pw) {
2152 ast_log (LOG_WARNING, "Unknown user '%s'\n", cat);
2153 continue;
2154 }
2155 }
2156 user_group = NULL;
2157 /* Check for duplicates */
2159 AST_LIST_TRAVERSE(&cli_perms, cp_entry, list) {
2160 if ((pw && cp_entry->uid == pw->pw_uid) || (gr && cp_entry->gid == gr->gr_gid)) {
2161 /* if it is duplicated, just added this new settings, to
2162 the current list. */
2163 user_group = cp_entry;
2164 break;
2165 }
2166 }
2168
2169 if (!user_group) {
2170 /* alloc space for the new user config. */
2171 user_group = ast_calloc(1, sizeof(*user_group));
2172 if (!user_group) {
2173 continue;
2174 }
2175 user_group->uid = (pw ? pw->pw_uid : -1);
2176 user_group->gid = (gr ? gr->gr_gid : -1);
2177 user_group->perms = ast_calloc(1, sizeof(*user_group->perms));
2178 if (!user_group->perms) {
2179 ast_free(user_group);
2180 continue;
2181 }
2182 }
2183 for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
2184 if (ast_strlen_zero(v->value)) {
2185 /* we need to check this condition cause it could break security. */
2186 ast_log(LOG_WARNING, "Empty permit/deny option in user '%s'\n", cat);
2187 continue;
2188 }
2189 if (!strcasecmp(v->name, "permit")) {
2190 perm = ast_calloc(1, sizeof(*perm));
2191 if (perm) {
2192 perm->permit = 1;
2193 perm->command = ast_strdup(v->value);
2194 }
2195 } else if (!strcasecmp(v->name, "deny")) {
2196 perm = ast_calloc(1, sizeof(*perm));
2197 if (perm) {
2198 perm->permit = 0;
2199 perm->command = ast_strdup(v->value);
2200 }
2201 } else {
2202 /* up to now, only 'permit' and 'deny' are possible values. */
2203 ast_log(LOG_WARNING, "Unknown '%s' option\n", v->name);
2204 continue;
2205 }
2206 if (perm) {
2207 /* Added the permission to the user's list. */
2208 AST_LIST_INSERT_TAIL(user_group->perms, perm, list);
2209 perm = NULL;
2210 }
2211 }
2213 AST_RWLIST_INSERT_TAIL(&cli_perms, user_group, list);
2215 }
2216
2217 ast_config_destroy(cfg);
2219 return 0;
2220}
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:3321
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
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
@ CONFIG_FLAG_FILEUNCHANGED
#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:190
#define ast_mutex_trylock(a)
Definition: lock.h:191
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:2084
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:199
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 3051 of file main/cli.c.

3052{
3053 print_uptimestr(fd, ast_tv(seconds, 0), prefix, 0);
3054}
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:908
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 2427 of file main/cli.c.

2428{
2429 if (e->inuse) {
2430 ast_log(LOG_WARNING, "Can't remove command that is in use\n");
2431 } else {
2433 AST_RWLIST_REMOVE(&helpers, e, list);
2436 ast_free(e->_full_cmd);
2437 e->_full_cmd = NULL;
2438 if (e->handler) {
2439 /* this is a new-style entry. Reset fields and free memory. */
2440 char *cmda = (char *) e->cmda;
2441 memset(cmda, '\0', sizeof(e->cmda));
2442 ast_free(e->command);
2443 e->command = NULL;
2444 e->usage = NULL;
2445 }
2446 }
2447 return 0;
2448}
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:885
static void remove_shutdown_command(struct ast_cli_entry *e)
Definition: main/cli.c:2420

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 2538 of file main/cli.c.

2539{
2540 int i, res = 0;
2541
2542 for (i = 0; i < len; i++)
2543 res |= ast_cli_unregister(e + i);
2544
2545 return res;
2546}
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
Definition: main/cli.c:2427

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 1860 of file main/cli.c.

1861{
1862 int wordlen = strlen(word), which = 0;
1863 struct ao2_container *cached_channels;
1864 char *ret = NULL;
1865 struct ao2_iterator iter;
1866 struct ast_channel_snapshot *snapshot;
1867
1868 if (pos != rpos) {
1869 return NULL;
1870 }
1871
1872 cached_channels = ast_channel_cache_all();
1873
1874 iter = ao2_iterator_init(cached_channels, 0);
1875 for (; (snapshot = ao2_iterator_next(&iter)); ao2_ref(snapshot, -1)) {
1876 if (!strncasecmp(word, snapshot->base->name, wordlen) && (++which > state)) {
1877 if (state != -1) {
1878 ret = ast_strdup(snapshot->base->name);
1879 ao2_ref(snapshot, -1);
1880 break;
1881 }
1882
1883 if (ast_cli_completion_add(ast_strdup(snapshot->base->name))) {
1884 ao2_ref(snapshot, -1);
1885 break;
1886 }
1887 }
1888 }
1889 ao2_iterator_destroy(&iter);
1890 ao2_ref(cached_channels, -1);
1891
1892 return ret;
1893}
#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:393
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 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
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
Definition: search.h:40
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 1482 of file main/cli.c.

1483{
1484 struct ast_channel *chan = obj;
1485 struct channel_set_debug_args *args = data;
1486
1487 ast_channel_lock(chan);
1488
1489 if (!(ast_channel_fin(chan) & DEBUGCHAN_FLAG) || !(ast_channel_fout(chan) & DEBUGCHAN_FLAG)) {
1490 if (args->is_off) {
1493 } else {
1496 }
1497 ast_cli(args->fd, "Debugging %s on channel %s\n", args->is_off ? "disabled" : "enabled",
1498 ast_channel_name(chan));
1499 }
1500
1501 ast_channel_unlock(chan);
1502
1503 return 0;
1504}
const char * ast_channel_name(const struct ast_channel *chan)
#define DEBUGCHAN_FLAG
Definition: channel.h:857
unsigned int ast_channel_fin(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2922
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:2923
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 2227 of file main/cli.c.

2228{
2230}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: main/cli.c:2538

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 2735 of file main/cli.c.

2736{
2737 if (!value) {
2738 return 0;
2739 }
2740
2741 if (!vec || AST_VECTOR_ADD_SORTED(vec, value, strcasecmp)) {
2742 if (vec) {
2743 ast_threadstorage_set_ptr(&completion_storage, NULL);
2744
2746 AST_VECTOR_FREE(vec);
2747 }
2748 ast_free(value);
2749
2750 return -1;
2751 }
2752
2753 return 0;
2754}
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_ADD_SORTED(vec, elem, cmp)
Add an element into a sorted vector.
Definition: vector.h:371

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::@333 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 2408 of file main/cli.c.

2409{
2410 struct ast_cli_entry *cur = NULL;
2411
2412 while ((cur = cli_next(cur))) {
2413 if (cur == e) {
2414 return 1;
2415 }
2416 }
2417 return 0;
2418}

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 961 of file main/cli.c.

962{
963 if (e) {
964 return AST_LIST_NEXT(e, list);
965 } else {
966 return AST_LIST_FIRST(&helpers);
967 }
968}
#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 2222 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 2084 of file main/cli.c.

2085{
2086 struct cli_perm *perm;
2087 struct usergroup_cli_perm *user_perm;
2088
2090 while ((user_perm = AST_LIST_REMOVE_HEAD(&cli_perms, list))) {
2091 while ((perm = AST_LIST_REMOVE_HEAD(user_perm->perms, list))) {
2092 ast_free(perm->command);
2093 ast_free(perm);
2094 }
2095 ast_free(user_perm);
2096 }
2098}
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
struct usergroup_cli_perm::@334 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 2390 of file main/cli.c.

2391{
2392 static char cmdline[80];
2393 int x;
2394 /* See how close we get, then print the candidate */
2395 const char *myargv[AST_MAX_CMD_LEN] = { NULL, };
2396
2398 for (x = 0; argv[x]; x++) {
2399 myargv[x] = argv[x];
2400 if (!find_cli(myargv, -1))
2401 break;
2402 }
2404 ast_join(cmdline, sizeof(cmdline), myargv);
2405 return cmdline;
2406}

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 2346 of file main/cli.c.

2347{
2348 int matchlen = -1; /* length of longest match so far */
2349 struct ast_cli_entry *cand = NULL, *e=NULL;
2350
2351 while ( (e = cli_next(e)) ) {
2352 /* word-by word regexp comparison */
2353 const char * const *src = cmds;
2354 const char * const *dst = e->cmda;
2355 int n = 0;
2356 for (;; dst++, src += n) {
2357 n = word_match(*src, *dst);
2358 if (n < 0)
2359 break;
2360 }
2361 if (ast_strlen_zero(*dst) || ((*dst)[0] == '[' && ast_strlen_zero(dst[1]))) {
2362 /* no more words in 'e' */
2363 if (ast_strlen_zero(*src)) /* exact match, cannot do better */
2364 break;
2365 /* Here, cmds has more words than the entry 'e' */
2366 if (match_type != 0) /* but we look for almost exact match... */
2367 continue; /* so we skip this one. */
2368 /* otherwise we like it (case 0) */
2369 } else { /* still words in 'e' */
2370 if (ast_strlen_zero(*src))
2371 continue; /* cmds is shorter than 'e', not good */
2372 /* Here we have leftover words in cmds and 'e',
2373 * but there is a mismatch. We only accept this one if match_type == -1
2374 * and this is the last word for both.
2375 */
2376 if (match_type != -1 || !ast_strlen_zero(src[1]) ||
2377 !ast_strlen_zero(dst[1])) /* not the one we look for */
2378 continue;
2379 /* good, we are in case match_type == -1 and mismatch on last word */
2380 }
2381 if (src - cmds > matchlen) { /* remember the candidate */
2382 matchlen = src - cmds;
2383 cand = e;
2384 }
2385 }
2386
2387 return e ? e : cand;
2388}

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 1895 of file main/cli.c.

1896{
1897#define FORMAT_STRING "%-25s %-20s %-20s\n"
1898
1899 struct ast_group_info *gi = NULL;
1900 int numchans = 0;
1901 regex_t regexbuf;
1902 int havepattern = 0;
1903
1904 switch (cmd) {
1905 case CLI_INIT:
1906 e->command = "group show channels";
1907 e->usage =
1908 "Usage: group show channels [pattern]\n"
1909 " Lists all currently active channels with channel group(s) specified.\n"
1910 " Optional regular expression pattern is matched to group names for each\n"
1911 " channel.\n";
1912 return NULL;
1913 case CLI_GENERATE:
1914 return NULL;
1915 }
1916
1917 if (a->argc < 3 || a->argc > 4)
1918 return CLI_SHOWUSAGE;
1919
1920 if (a->argc == 4) {
1921 if (regcomp(&regexbuf, a->argv[3], REG_EXTENDED | REG_NOSUB))
1922 return CLI_SHOWUSAGE;
1923 havepattern = 1;
1924 }
1925
1926 ast_cli(a->fd, FORMAT_STRING, "Channel", "Group", "Category");
1927
1929
1931 while (gi) {
1932 if (!havepattern || !regexec(&regexbuf, gi->group, 0, NULL, 0)) {
1933 ast_cli(a->fd, FORMAT_STRING, ast_channel_name(gi->chan), gi->group, (ast_strlen_zero(gi->category) ? "(default)" : gi->category));
1934 numchans++;
1935 }
1936 gi = AST_LIST_NEXT(gi, group_list);
1937 }
1938
1940
1941 if (havepattern)
1942 regfree(&regexbuf);
1943
1944 ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
1945 return CLI_SUCCESS;
1946#undef FORMAT_STRING
1947}
#define ESS(x)
Definition: cli.h:59
int ast_app_group_list_unlock(void)
Unlock the group count list.
Definition: main/app.c:2341
struct ast_group_info * ast_app_group_list_head(void)
Get the head of the group count list.
Definition: main/app.c:2336
int ast_app_group_list_rdlock(void)
Read Lock the group count list.
Definition: main/app.c:2331
#define FORMAT_STRING
channel group info
Definition: channel.h:2915
struct ast_group_info::@210 group_list
char * category
Definition: channel.h:2917
char * group
Definition: channel.h:2918
struct ast_channel * chan
Definition: channel.h:2916

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 1099 of file main/cli.c.

1100{
1101#define FORMAT_STRING "%-64.64s %-32.32s %-7.7s %-30.30s\n"
1102#define FORMAT_STRING2 "%-64.64s %-32.32s %-7.7s %-30.30s\n"
1103#define CONCISE_FORMAT_STRING "%s!%s!%s!%d!%s!%s!%s!%s!%s!%s!%d!%s!%s!%s\n"
1104#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"
1105#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"
1106
1107 struct ao2_container *channels;
1108 struct ao2_iterator it_chans;
1109 struct ast_channel_snapshot *cs;
1110 int numchans = 0, concise = 0, verbose = 0, count = 0;
1111
1112 switch (cmd) {
1113 case CLI_INIT:
1114 e->command = "core show channels [concise|verbose|count]";
1115 e->usage =
1116 "Usage: core show channels [concise|verbose|count]\n"
1117 " Lists currently defined channels and some information about them. If\n"
1118 " 'concise' is specified, the format is abridged and in a more easily\n"
1119 " machine parsable format. If 'verbose' is specified, the output includes\n"
1120 " more and longer fields. If 'count' is specified only the channel and call\n"
1121 " count is output.\n";
1122 return NULL;
1123
1124 case CLI_GENERATE:
1125 return NULL;
1126 }
1127
1128 if (a->argc == e->args) {
1129 if (!strcasecmp(a->argv[e->args-1],"concise"))
1130 concise = 1;
1131 else if (!strcasecmp(a->argv[e->args-1],"verbose"))
1132 verbose = 1;
1133 else if (!strcasecmp(a->argv[e->args-1],"count"))
1134 count = 1;
1135 else
1136 return CLI_SHOWUSAGE;
1137 } else if (a->argc != e->args - 1)
1138 return CLI_SHOWUSAGE;
1139
1141
1142 if (!count) {
1143 if (!concise && !verbose)
1144 ast_cli(a->fd, FORMAT_STRING2, "Channel", "Location", "State", "Application(Data)");
1145 else if (verbose)
1146 ast_cli(a->fd, VERBOSE_FORMAT_STRING2, "Channel", "Context", "Extension", "Priority", "State", "Application", "Data",
1147 "CallerID", "Duration", "Accountcode", "PeerAccount", "BridgeID");
1148 }
1149
1150 it_chans = ao2_iterator_init(channels, 0);
1151 for (; (cs = ao2_iterator_next(&it_chans)); ao2_ref(cs, -1)) {
1152 char durbuf[16] = "-";
1153
1154 if (!count) {
1155 if ((concise || verbose) && !ast_tvzero(cs->base->creationtime)) {
1156 int duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->base->creationtime) / 1000);
1157 if (verbose) {
1158 int durh = duration / 3600;
1159 int durm = (duration % 3600) / 60;
1160 int durs = duration % 60;
1161 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
1162 } else {
1163 snprintf(durbuf, sizeof(durbuf), "%d", duration);
1164 }
1165 }
1166 if (concise) {
1168 S_OR(cs->dialplan->appl, "(None)"),
1169 cs->dialplan->data,
1170 cs->caller->number,
1171 cs->base->accountcode,
1172 cs->peer->account,
1173 cs->amaflags,
1174 durbuf,
1175 cs->bridge->id,
1176 cs->base->uniqueid);
1177 } else if (verbose) {
1179 S_OR(cs->dialplan->appl, "(None)"),
1180 S_OR(cs->dialplan->data, "(Empty)"),
1181 cs->caller->number,
1182 durbuf,
1183 cs->base->accountcode,
1184 cs->peer->account,
1185 cs->bridge->id);
1186 } else {
1187 char locbuf[40] = "(None)";
1188 char appdata[40] = "(None)";
1189
1191 snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", cs->dialplan->exten, cs->dialplan->context, cs->dialplan->priority);
1192 }
1193 if (!ast_strlen_zero(cs->dialplan->appl)) {
1194 snprintf(appdata, sizeof(appdata), "%s(%s)", cs->dialplan->appl, S_OR(cs->dialplan->data, ""));
1195 }
1196 ast_cli(a->fd, FORMAT_STRING, cs->base->name, locbuf, ast_state2str(cs->state), appdata);
1197 }
1198 }
1199 }
1200 ao2_iterator_destroy(&it_chans);
1201
1202 if (!concise) {
1203 numchans = ast_active_channels();
1204 ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
1206 ast_cli(a->fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
1208 ((double)ast_active_calls() / (double)ast_option_maxcalls) * 100.0);
1209 else
1210 ast_cli(a->fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
1211
1212 ast_cli(a->fd, "%d call%s processed\n", ast_processed_calls(), ESS(ast_processed_calls()));
1213 }
1214 ao2_ref(channels, -1);
1215
1216 return CLI_SUCCESS;
1217
1218#undef FORMAT_STRING
1219#undef FORMAT_STRING2
1220#undef CONCISE_FORMAT_STRING
1221#undef VERBOSE_FORMAT_STRING
1222#undef VERBOSE_FORMAT_STRING2
1223}
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:79
#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:4760
int ast_processed_calls(void)
Retrieve the total number of calls processed through the PBX since last restart.
Definition: pbx.c:4765
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 1346 of file main/cli.c.

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

1987{
1988 extern int malloc_trim(size_t __pad) __THROW;
1989
1990 switch (cmd) {
1991 case CLI_INIT:
1992 e->command = "malloc trim";
1993 e->usage =
1994 "Usage: malloc trim\n"
1995 " Try to give excess memory back to the OS.\n";
1996 return NULL;
1997 case CLI_GENERATE:
1998 return NULL;
1999 }
2000
2001 if (malloc_trim(0)) {
2002 ast_cli(a->fd, "Returned some memory to the OS.\n");
2003 } else {
2004 ast_cli(a->fd, "No memory returned to the OS.\n");
2005 }
2006
2007 return CLI_SUCCESS;
2008}

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 1327 of file main/cli.c.

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

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 1282 of file main/cli.c.

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

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 1949 of file main/cli.c.

1950{
1951 switch (cmd) {
1952 case CLI_INIT:
1953 e->command = "core waitfullybooted";
1954 e->usage =
1955 "Usage: core waitfullybooted\n"
1956 " Wait until Asterisk has fully booted.\n";
1957 return NULL;
1958 case CLI_GENERATE:
1959 return NULL;
1960 }
1961
1963 usleep(100);
1964 }
1965
1966 ast_cli(a->fd, "Asterisk has fully booted.\n");
1967
1968 return CLI_SUCCESS;
1969}
struct ast_flags ast_options
Definition: options.c:61
@ AST_OPT_FLAG_FULLY_BOOTED
Definition: options.h:58
#define ast_test_flag(p, flag)
Definition: utils.h:63

References a, ast_cli(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, ast_test_flag, 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 1423 of file main/cli.c.

1424{
1425 char *buf, *obuf;
1426 int buflen = 2048;
1427 int len = 0;
1428 char **matches;
1429 int x, matchlen;
1430
1431 switch (cmd) {
1432 case CLI_INIT:
1433 e->command = "_command matchesarray";
1434 e->usage =
1435 "Usage: _command matchesarray \"<line>\" text \n"
1436 " This function is used internally to help with command completion and should.\n"
1437 " never be called by the user directly.\n";
1438 return NULL;
1439 case CLI_GENERATE:
1440 return NULL;
1441 }
1442
1443 if (a->argc != 4)
1444 return CLI_SHOWUSAGE;
1445 if (!(buf = ast_malloc(buflen)))
1446 return CLI_FAILURE;
1447 buf[len] = '\0';
1448 matches = ast_cli_completion_matches(a->argv[2], a->argv[3]);
1449 if (matches) {
1450 for (x=0; matches[x]; x++) {
1451 matchlen = strlen(matches[x]) + 1;
1452 if (len + matchlen >= buflen) {
1453 buflen += matchlen * 3;
1454 obuf = buf;
1455 if (!(buf = ast_realloc(obuf, buflen)))
1456 /* Memory allocation failure... Just free old buffer and be done */
1457 ast_free(obuf);
1458 }
1459 if (buf)
1460 len += sprintf( buf + len, "%s ", matches[x]);
1461 ast_free(matches[x]);
1462 matches[x] = NULL;
1463 }
1464 ast_free(matches);
1465 }
1466
1467 if (buf) {
1468 ast_cli(a->fd, "%s%s",buf, AST_CLI_COMPLETE_EOF);
1469 ast_free(buf);
1470 } else
1471 ast_cli(a->fd, "NULL\n");
1472
1473 return CLI_SUCCESS;
1474}
#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:2700

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:1567

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 1506 of file main/cli.c.

1507{
1508 struct ast_channel *c = NULL;
1509 static const char * const completions_all[] = { "all", NULL };
1510 static const char * const completions_off[] = { "off", NULL };
1511 struct channel_set_debug_args args = {
1512 .fd = a->fd,
1513 };
1514
1515 switch (cmd) {
1516 case CLI_INIT:
1517 e->command = "core set debug channel";
1518 e->usage =
1519 "Usage: core set debug channel <all|channel> [off]\n"
1520 " Enables/disables debugging on all or on a specific channel.\n";
1521 return NULL;
1522 case CLI_GENERATE:
1523 if (a->pos == 4) {
1524 char *complete = ast_cli_complete(a->word, completions_all, a->n);
1525 if (!complete) {
1526 complete = ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
1527 }
1528 return complete;
1529 } else if (a->pos == 5) {
1530 return ast_cli_complete(a->word, completions_off, a->n);
1531 }
1532
1533 return NULL;
1534 }
1535
1536 if (cmd == (CLI_HANDLER + 1000)) {
1537 /* called from handle_nodebugchan_deprecated */
1538 args.is_off = 1;
1539 } else if (a->argc == e->args + 2) {
1540 /* 'core set debug channel {all|chan_id}' */
1541 if (!strcasecmp(a->argv[e->args + 1], "off"))
1542 args.is_off = 1;
1543 else
1544 return CLI_SHOWUSAGE;
1545 } else if (a->argc != e->args + 1) {
1546 return CLI_SHOWUSAGE;
1547 }
1548
1549 if (!strcasecmp("all", a->argv[e->args])) {
1550 if (args.is_off) {
1551 global_fin &= ~DEBUGCHAN_FLAG;
1552 global_fout &= ~DEBUGCHAN_FLAG;
1553 } else {
1556 }
1558 } else {
1559 if ((c = ast_channel_get_by_name(a->argv[e->args]))) {
1562 } else {
1563 ast_cli(a->fd, "No such channel %s\n", a->argv[e->args]);
1564 }
1565 }
1566
1567 ast_cli(a->fd, "Debugging on new channels is %s\n", args.is_off ? "disabled" : "enabled");
1568
1569 return CLI_SUCCESS;
1570}
@ 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:1278
unsigned long global_fin
Definition: channel.c:95
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
unsigned long global_fout
Definition: channel.h:866
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
static int channel_set_debug(void *obj, void *arg, void *data, int flags)
Definition: main/cli.c:1482
char * ast_cli_complete(const char *word, const char *const choices[], int state)
Definition: main/cli.c:1841
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:1860
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_HANDLER, 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.

Referenced by handle_nodebugchan_deprecated().

◆ 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:1374
@ 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 1572 of file main/cli.c.

1573{
1574 const char *argv4 = a->argv ? S_OR(a->argv[4], "") : "";
1575 int offset = strncasecmp(argv4, "off", strlen(argv4)) ? 0 : 1;
1576
1577 switch (cmd) {
1578 case CLI_INIT:
1579 e->command = "core set debug category";
1580 e->usage =
1581 "Usage: core set debug category <category>[:<sublevel>] [category[:<sublevel] ...]\n"
1582 " core set debug category off [<category> [<category>] ...]\n\n"
1583 " Allows enabling and disabling debug logging categories.\n"
1584 " When a category is enabled all relevant debug messages are logged\n"
1585 " for a given category. However, if a sublevel is specified only\n"
1586 " those categorized messages at or below the coded debug sublevel\n"
1587 " are logged.\n";
1588 return NULL;
1589
1590 case CLI_GENERATE:
1591 if (a->pos < e->args) {
1592 return NULL;
1593 }
1594
1595 if (a->pos == 4 && offset) {
1597 }
1598
1599 return ast_debug_category_complete(a->argv + 4,
1600 a->pos - e->args, a->word, a->n - 1);
1601 }
1602
1603 if (a->argc <= e->args) {
1604 return CLI_SHOWUSAGE;
1605 }
1606
1607 ast_debug_category_set_sublevels(a->argv + e->args + offset, a->argc - e->args - offset,
1609
1610 return CLI_SUCCESS;
1611}
#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_flag(&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_flag(&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:69
int option_trace
Definition: options.c:71
@ AST_OPT_FLAG_TRACE_MODULE
Definition: options.h:88
@ AST_OPT_FLAG_DEBUG_MODULE
Definition: options.h:86
#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_flag(p, flag)
Definition: utils.h:77
#define ast_set_flag(p, flag)
Definition: utils.h:70

References a, ast_cli_entry::args, ast_calloc, ast_clear_flag, 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_flag, 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 2582 of file main/cli.c.

2583{
2584 char fullcmd[80];
2585 struct ast_cli_entry *my_e;
2586 char *res = CLI_SUCCESS;
2587
2588 if (cmd == CLI_INIT) {
2589 e->command = "core show help";
2590 e->usage =
2591 "Usage: core show help [topic]\n"
2592 " When called with a topic as an argument, displays usage\n"
2593 " information on the given command. If called without a\n"
2594 " topic, it provides a list of commands.\n";
2595 return NULL;
2596
2597 } else if (cmd == CLI_GENERATE) {
2598 /* skip first 14 or 15 chars, "core show help " */
2599 int l = strlen(a->line);
2600
2601 if (l > 15) {
2602 l = 15;
2603 }
2604 /* XXX watch out, should stop to the non-generator parts */
2605 return __ast_cli_generator(a->line + l, a->word, a->n, 0);
2606 }
2607 if (a->argc == e->args) {
2608 return help1(a->fd, NULL, 0);
2609 }
2610
2612 my_e = find_cli(a->argv + 3, 1); /* try exact match first */
2613 if (!my_e) {
2614 res = help1(a->fd, a->argv + 3, 1 /* locked */);
2616 return res;
2617 }
2618 if (my_e->usage)
2619 ast_cli(a->fd, "%s", my_e->usage);
2620 else {
2621 ast_join(fullcmd, sizeof(fullcmd), a->argv + 3);
2622 ast_cli(a->fd, "No help text available for '%s'.\n", fullcmd);
2623 }
2625 return res;
2626}
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:2552

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:1824
@ 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:1270

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 1003 of file main/cli.c.

1004{
1005 const char *like;
1006
1007 switch (cmd) {
1008 case CLI_INIT:
1009 e->command = "module show [like]";
1010 e->usage =
1011 "Usage: module show [like keyword]\n"
1012 " Shows Asterisk modules currently in use, and usage statistics.\n";
1013 return NULL;
1014
1015 case CLI_GENERATE:
1016 if (a->pos == e->args) {
1017 return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_LOADED);
1018 } else {
1019 return NULL;
1020 }
1021 }
1022 /* all the above return, so we proceed with the handler.
1023 * we are guaranteed to have argc >= e->args
1024 */
1025 if (a->argc == e->args - 1)
1026 like = "";
1027 else if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args-1], "like") )
1028 like = a->argv[e->args];
1029 else
1030 return CLI_SHOWUSAGE;
1031
1033 climodentryfd = a->fd; /* global, protected by climodentrylock */
1034 ast_cli(a->fd, MODLIST_FORMAT2, "Module", "Description", "Use Count", "Status", "Support Level");
1035 ast_cli(a->fd,"%d modules loaded\n", ast_update_module_list(modlist_modentry, like));
1036 climodentryfd = -1;
1038 return CLI_SUCCESS;
1039}
#define ast_mutex_lock(a)
Definition: lock.h:189
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:895
static int climodentryfd
Definition: main/cli.c:893
#define MODLIST_FORMAT2
Definition: main/cli.c:890
static ast_mutex_t climodentrylock
Definition: main/cli.c:892
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:2583
@ 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_nodebugchan_deprecated()

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

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

1614{
1615 char *res;
1616
1617 switch (cmd) {
1618 case CLI_INIT:
1619 e->command = "no debug channel";
1620 return NULL;
1621 case CLI_HANDLER:
1622 /* exit out of switch statement */
1623 break;
1624 default:
1625 return NULL;
1626 }
1627
1628 if (a->argc != e->args + 1)
1629 return CLI_SHOWUSAGE;
1630
1631 /* add a 'magic' value to the CLI_HANDLER command so that
1632 * handle_core_set_debug_channel() will act as if 'off'
1633 * had been specified as part of the command
1634 */
1636
1637 return res;
1638}
static char * handle_core_set_debug_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: main/cli.c:1506

References a, ast_cli_entry::args, CLI_HANDLER, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, handle_core_set_debug_channel(), and NULL.

◆ 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 /* "module refresh <mod>" */
811 switch (cmd) {
812 case CLI_INIT:
813 e->command = "module refresh";
814 e->usage =
815 "Usage: module refresh <module name>\n"
816 " Unloads and loads the specified module into Asterisk.\n";
817 return NULL;
818
819 case CLI_GENERATE:
820 if (a->pos != e->args) {
821 return NULL;
822 }
823 return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_UNLOAD);
824 }
825 if (a->argc != e->args + 1) {
826 return CLI_SHOWUSAGE;
827 }
828 if (ast_unload_resource(a->argv[e->args], AST_FORCE_SOFT)) {
829 ast_cli(a->fd, "Unable to unload resource %s\n", a->argv[e->args]);
830 return CLI_FAILURE;
831 }
832 if (ast_load_resource(a->argv[e->args])) {
833 ast_cli(a->fd, "Unable to load module %s\n", a->argv[e->args]);
834 return CLI_FAILURE;
835 }
836 ast_cli(a->fd, "Unloaded and loaded %s\n", a->argv[e->args]);
837 return CLI_SUCCESS;
838}
int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode)
Unload a module.
Definition: loader.c:1219
@ AST_FORCE_SOFT
Definition: module.h:62
@ AST_MODULE_HELPER_UNLOAD
Definition: module.h:135

References a, ast_cli_entry::args, ast_cli(), AST_FORCE_SOFT, ast_load_resource(), 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_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 1043 of file main/cli.c.

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

1641{
1642 struct ast_channel *chan;
1643 struct timeval now;
1644 char cdrtime[256];
1645 struct ast_str *obuf;/*!< Buffer for CDR variables. */
1646 struct ast_str *output;/*!< Accumulation buffer for all output. */
1647 long elapsed_seconds=0;
1648 int hour=0, min=0, sec=0;
1649 struct ast_var_t *var;
1650 struct ast_str *write_transpath = ast_str_alloca(256);
1651 struct ast_str *read_transpath = ast_str_alloca(256);
1652 struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1653 struct ast_bridge *bridge;
1655 char callid_buf[32];
1656 int stream_num;
1657
1658 switch (cmd) {
1659 case CLI_INIT:
1660 e->command = "core show channel";
1661 e->usage =
1662 "Usage: core show channel <channel>\n"
1663 " Shows lots of information about the specified channel.\n";
1664 return NULL;
1665 case CLI_GENERATE:
1666 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
1667 }
1668
1669 if (a->argc != 4) {
1670 return CLI_SHOWUSAGE;
1671 }
1672
1673 obuf = ast_str_thread_get(&ast_str_thread_global_buf, 16);
1674 if (!obuf) {
1675 return CLI_FAILURE;
1676 }
1677
1678 chan = ast_channel_get_by_name(a->argv[3]);
1679 if (!chan) {
1680 ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
1681
1682 return CLI_SUCCESS;
1683 }
1684
1685 output = ast_str_create(8192);
1686 if (!output) {
1687 ast_channel_unref(chan);
1688
1689 return CLI_FAILURE;
1690 }
1691
1692 now = ast_tvnow();
1693 ast_channel_lock(chan);
1694
1696 elapsed_seconds = now.tv_sec - ast_channel_creationtime(chan).tv_sec;
1697 hour = elapsed_seconds / 3600;
1698 min = (elapsed_seconds % 3600) / 60;
1699 sec = elapsed_seconds % 60;
1700 snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
1701 } else {
1702 strcpy(cdrtime, "N/A");
1703 }
1704
1705 ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath);
1706 ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath);
1707
1708 bridge = ast_channel_get_bridge(chan);
1709 callid_buf[0] = '\0';
1710 callid = ast_channel_callid(chan);
1711 if (callid) {
1712 ast_callid_strnprint(callid_buf, sizeof(callid_buf), callid);
1713 }
1714
1715 ast_str_append(&output, 0,
1716 " -- General --\n"
1717 " Name: %s\n"
1718 " Type: %s\n"
1719 " UniqueID: %s\n"
1720 " LinkedID: %s\n"
1721 " Caller ID: %s\n"
1722 " Caller ID Name: %s\n"
1723 "Connected Line ID: %s\n"
1724 "Connected Line ID Name: %s\n"
1725 "Eff. Connected Line ID: %s\n"
1726 "Eff. Connected Line ID Name: %s\n"
1727 " DNID Digits: %s\n"
1728 " Language: %s\n"
1729 " State: %s (%u)\n"
1730 " NativeFormats: %s\n"
1731 " WriteFormat: %s\n"
1732 " ReadFormat: %s\n"
1733 " WriteTranscode: %s %s\n"
1734 " ReadTranscode: %s %s\n"
1735 " Time to Hangup: %ld\n"
1736 " Elapsed Time: %s\n"
1737 " Bridge ID: %s\n"
1738 " -- PBX --\n"
1739 " Context: %s\n"
1740 " Extension: %s\n"
1741 " Priority: %d\n"
1742 " Call Group: %llu\n"
1743 " Pickup Group: %llu\n"
1744 " Application: %s\n"
1745 " Data: %s\n"
1746 " Call Identifer: %s\n",
1747 ast_channel_name(chan),
1748 ast_channel_tech(chan)->type,
1751 S_COR(ast_channel_caller(chan)->id.number.valid,
1752 ast_channel_caller(chan)->id.number.str, "(N/A)"),
1753 S_COR(ast_channel_caller(chan)->id.name.valid,
1754 ast_channel_caller(chan)->id.name.str, "(N/A)"),
1755 S_COR(ast_channel_connected(chan)->id.number.valid,
1756 ast_channel_connected(chan)->id.number.str, "(N/A)"),
1757 S_COR(ast_channel_connected(chan)->id.name.valid,
1758 ast_channel_connected(chan)->id.name.str, "(N/A)"),
1760 ast_channel_connected_effective_id(chan).number.str, "(N/A)"),
1762 ast_channel_connected_effective_id(chan).name.str, "(N/A)"),
1763 S_OR(ast_channel_dialed(chan)->number.str, "(N/A)"),
1766 ast_channel_state(chan),
1770 ast_str_strlen(write_transpath) ? "Yes" : "No",
1771 ast_str_buffer(write_transpath),
1772 ast_str_strlen(read_transpath) ? "Yes" : "No",
1773 ast_str_buffer(read_transpath),
1774 (long)ast_channel_whentohangup(chan)->tv_sec,
1775 cdrtime,
1776 bridge ? bridge->uniqueid : "(Not bridged)",
1777 ast_channel_context(chan),
1778 ast_channel_exten(chan),
1782 S_OR(ast_channel_appl(chan), "(N/A)"),
1783 S_OR(ast_channel_data(chan), "(Empty)"),
1784 S_OR(callid_buf, "(None)")
1785 );
1786
1787 ast_str_append(&output, 0, " Variables:\n");
1788
1789 AST_LIST_TRAVERSE(ast_channel_varshead(chan), var, entries) {
1790 ast_str_append(&output, 0, "%s=%s\n", ast_var_name(var), ast_var_value(var));
1791 }
1792
1793 if (!(ast_channel_tech(chan)->properties & AST_CHAN_TP_INTERNAL)
1794 && ast_cdr_serialize_variables(ast_channel_name(chan), &obuf, '=', '\n')) {
1795 ast_str_append(&output, 0, " CDR Variables:\n%s\n", ast_str_buffer(obuf));
1796 }
1797
1798 ast_str_append(&output, 0, " -- Streams --\n");
1799 for (stream_num = 0; stream_num < ast_stream_topology_get_count(ast_channel_get_stream_topology(chan)); stream_num++) {
1801 struct ast_variable *metadata = ast_stream_get_metadata_list(stream);
1802
1803 ast_str_append(&output, 0,
1804 "Name: %s\n"
1805 " Type: %s\n"
1806 " State: %s\n"
1807 " Group: %d\n"
1808 " Formats: %s\n"
1809 " Metadata:\n",
1810 ast_stream_get_name(stream),
1813 ast_stream_get_group(stream),
1815 );
1816
1817 if (metadata) {
1818 struct ast_variable *v;
1819 for(v = metadata; v; v = v->next) {
1820 ast_str_append(&output, 0, " %s: %s\n", v->name, v->value);
1821 }
1822 ast_variables_destroy(metadata);
1823 }
1824 }
1825
1826 ast_channel_unlock(chan);
1827
1828 ast_cli(a->fd, "%s", ast_str_buffer(output));
1829 ast_free(output);
1830
1831 ao2_cleanup(bridge);
1832 ast_channel_unref(chan);
1833
1834 return CLI_SUCCESS;
1835}
#define var
Definition: ast_expr2f.c:605
#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:3415
static const char type[]
Definition: chan_ooh323.c:109
const char * ast_channel_linkedid(const 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:971
const char * ast_channel_data(const struct ast_channel *chan)
struct varshead * ast_channel_varshead(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:10534
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_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:2276
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:788
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
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:1077
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:349
ast_callid callid
Definition: bridge.h:361
const ast_string_field uniqueid
Definition: bridge.h:401
Number structure.
Definition: app_followme.c:154
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

References a, ao2_cleanup, 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_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_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, 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 970 of file main/cli.c.

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

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 1225 of file main/cli.c.

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

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 840 of file main/cli.c.

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

2553{
2554 char matchstr[80] = "";
2555 struct ast_cli_entry *e = NULL;
2556 int len = 0;
2557 int found = 0;
2558
2559 if (match) {
2560 ast_join(matchstr, sizeof(matchstr), match);
2561 len = strlen(matchstr);
2562 }
2563 if (!locked)
2565 while ( (e = cli_next(e)) ) {
2566 /* Hide commands that start with '_' */
2567 if (e->_full_cmd[0] == '_')
2568 continue;
2569 if (match && strncasecmp(matchstr, e->_full_cmd, len))
2570 continue;
2571 ast_cli(fd, "%-30s -- %s\n", e->_full_cmd,
2572 S_OR(e->summary, "<no description available>"));
2573 found++;
2574 }
2575 if (!locked)
2577 if (!found && matchstr[0])
2578 ast_cli(fd, "No such command '%s'.\n", matchstr);
2579 return CLI_SUCCESS;
2580}
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:2362

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 2296 of file main/cli.c.

2298{
2299 int lw;
2300 char *s, *t1;
2301
2302 *actual = 0;
2303 if (ast_strlen_zero(token))
2304 return NULL;
2305 if (ast_strlen_zero(word))
2306 word = ""; /* dummy */
2307 lw = strlen(word);
2308 if (strcspn(word, cli_rsvd) != lw)
2309 return NULL; /* no match if word has reserved chars */
2310 if (strchr(cli_rsvd, token[0]) == NULL) { /* regular match */
2311 if (strncasecmp(token, word, lw)) /* no match */
2312 return NULL;
2313 *actual = 1;
2314 return (pos != 0) ? NULL : ast_strdup(token);
2315 }
2316 /* now handle regexp match */
2317
2318 /* Wildcard always matches, so we never do is_prefix on them */
2319
2320 t1 = ast_strdupa(token + 1); /* copy, skipping first char */
2321 while (pos >= 0 && (s = strsep(&t1, cli_rsvd)) && *s) {
2322 if (*s == '%') /* wildcard */
2323 continue;
2324 if (strncasecmp(s, word, lw)) /* no match */
2325 continue;
2326 (*actual)++;
2327 if (pos-- == 0)
2328 return ast_strdup(s);
2329 }
2330 return NULL;
2331}
char * strsep(char **str, const char *delims)
static const char cli_rsvd[]
Definition: main/cli.c:2059

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 895 of file main/cli.c.

898{
899 /* Comparing the like with the module */
900 if (strcasestr(module, like) ) {
901 ast_cli(climodentryfd, MODLIST_FORMAT, module, description, usecnt,
903 return 1;
904 }
905 return 0;
906}
jack_status_t status
Definition: app_jack.c:146
static int usecnt
Definition: chan_ooh323.c:332
char * strcasestr(const char *, const char *)
#define MODLIST_FORMAT
Definition: main/cli.c:889
const char * ast_module_support_level_to_string(enum ast_module_support_level support_level)
Definition: loader.c:2771

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 2846 of file main/cli.c.

2847{
2848 int i;
2849 for (i = 0; dst[i]; i++) {
2850 if (dst[i][0] != '[')
2851 return -1;
2852 }
2853 return 0;
2854}

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 2628 of file main/cli.c.

2629{
2630 char *duplicate, *cur;
2631 int x = 0;
2632 int quoted = 0;
2633 int escaped = 0;
2634 int whitespace = 1;
2635 int dummy = 0;
2636
2637 if (trailingwhitespace == NULL)
2638 trailingwhitespace = &dummy;
2639 *trailingwhitespace = 0;
2640 if (s == NULL) /* invalid, though! */
2641 return NULL;
2642 /* make a copy to store the parsed string */
2643 if (!(duplicate = ast_strdup(s)))
2644 return NULL;
2645
2646 cur = duplicate;
2647
2648 /* Remove leading spaces from the command */
2649 while (isspace(*s)) {
2650 cur++;
2651 s++;
2652 }
2653
2654 /* scan the original string copying into cur when needed */
2655 for (; *s ; s++) {
2656 if (x >= max - 1) {
2657 ast_log(LOG_WARNING, "Too many arguments, truncating at %s\n", s);
2658 break;
2659 }
2660 if (*s == '"' && !escaped) {
2661 quoted = !quoted;
2662 if (quoted && whitespace) {
2663 /* start a quoted string from previous whitespace: new argument */
2664 argv[x++] = cur;
2665 whitespace = 0;
2666 }
2667 } else if ((*s == ' ' || *s == '\t') && !(quoted || escaped)) {
2668 /* If we are not already in whitespace, and not in a quoted string or
2669 processing an escape sequence, and just entered whitespace, then
2670 finalize the previous argument and remember that we are in whitespace
2671 */
2672 if (!whitespace) {
2673 *cur++ = '\0';
2674 whitespace = 1;
2675 }
2676 } else if (*s == '\\' && !escaped) {
2677 escaped = 1;
2678 } else {
2679 if (whitespace) {
2680 /* we leave whitespace, and are not quoted. So it's a new argument */
2681 argv[x++] = cur;
2682 whitespace = 0;
2683 }
2684 *cur++ = *s;
2685 escaped = 0;
2686 }
2687 }
2688 /* Null terminate */
2689 *cur++ = '\0';
2690 /* XXX put a NULL in the last argument, because some functions that take
2691 * the array may want a null-terminated array.
2692 * argc still reflects the number of non-NULL entries.
2693 */
2694 argv[x] = NULL;
2695 *argc = x;
2696 *trailingwhitespace = whitespace;
2697 return duplicate;
2698}
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 908 of file main/cli.c.

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

2421{
2425}
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
Definition: vector.h:571
#define AST_VECTOR_REMOVE_ELEM_UNORDERED(vec, elem, cleanup)
Remove an element from a vector.
Definition: vector.h:583

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 2065 of file main/cli.c.

2066{
2067 int i;
2068 char buf[80];
2069
2070 ast_join(buf, sizeof(buf), e->cmda);
2071 e->_full_cmd = ast_strdup(buf);
2072 if (!e->_full_cmd) {
2073 ast_log(LOG_WARNING, "-- cannot allocate <%s>\n", buf);
2074 return -1;
2075 }
2076 e->cmdlen = strcspn(e->_full_cmd, cli_rsvd);
2077 for (i = 0; e->cmda[i]; i++)
2078 ;
2079 e->args = i;
2080 return 0;
2081}

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 2257 of file main/cli.c.

2258{
2259 int l;
2260 char *pos;
2261
2262 if (ast_strlen_zero(cmd) || ast_strlen_zero(cli_word))
2263 return -1;
2264 if (!strchr(cli_rsvd, cli_word[0])) /* normal match */
2265 return (strcasecmp(cmd, cli_word) == 0) ? 1 : -1;
2266 l = strlen(cmd);
2267 /* wildcard match - will extend in the future */
2268 if (l > 0 && cli_word[0] == '%') {
2269 return 1; /* wildcard */
2270 }
2271
2272 /* Start a search for the command entered against the cli word in question */
2273 pos = strcasestr(cli_word, cmd);
2274 while (pos) {
2275
2276 /*
2277 *Check if the word matched with is surrounded by reserved characters on both sides
2278 * and isn't at the beginning of the cli_word since that would make it check in a location we shouldn't know about.
2279 * If it is surrounded by reserved chars and isn't at the beginning, it's a match.
2280 */
2281 if (pos != cli_word && strchr(cli_rsvd, pos[-1]) && strchr(cli_rsvd, pos[l])) {
2282 return 1; /* valid match */
2283 }
2284
2285 /* Ok, that one didn't match, strcasestr to the next appearance of the command and start over.*/
2286 pos = strcasestr(pos + 1, cmd);
2287 }
2288 /* If no matches were found over the course of the while loop, we hit the end of the string. It's a mismatch. */
2289 return -1;
2290}

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 2046 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 2014 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 2059 of file main/cli.c.

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

◆ climodentryfd

int climodentryfd = -1
static

Definition at line 893 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 892 of file main/cli.c.

Referenced by handle_modlist().

◆ current

size_t current

◆ 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().