Asterisk - The Open Source Telephony Project GIT-master-2070bb5
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 894 of file main/cli.c.

◆ MODLIST_FORMAT2

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

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

◆ NEEDCOMMA

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

◆ SECOND

#define SECOND   (1)

◆ TRACE_HANDLER

#define TRACE_HANDLER   1

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

◆ VERBOSE_FORMAT_STRING

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

◆ VERBOSE_FORMAT_STRING2

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

◆ VERBOSE_HANDLER

#define VERBOSE_HANDLER   2

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

◆ WEEK

#define WEEK   (DAY*7)

◆ YEAR

#define YEAR   (DAY*365)

Function Documentation

◆ __ast_cli_generator()

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

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

2872{
2873 const char *argv[AST_MAX_ARGS];
2874 struct ast_cli_entry *e = NULL;
2875 int x = 0, argindex, matchlen;
2876 int matchnum=0;
2877 char *ret = NULL;
2878 char matchstr[80] = "";
2879 int tws = 0;
2880 /* Split the argument into an array of words */
2881 char *duplicate = parse_args(text, &x, argv, ARRAY_LEN(argv), &tws);
2882
2883 if (!duplicate) /* malloc error */
2884 return NULL;
2885
2886 /* Compute the index of the last argument (could be an empty string) */
2887 argindex = (!ast_strlen_zero(word) && x>0) ? x-1 : x;
2888
2889 /* rebuild the command, ignore terminating white space and flatten space */
2890 ast_join(matchstr, sizeof(matchstr)-1, argv);
2891 matchlen = strlen(matchstr);
2892 if (tws) {
2893 strcat(matchstr, " "); /* XXX */
2894 if (matchlen)
2895 matchlen++;
2896 }
2897 if (lock)
2899 while ( (e = cli_next(e)) ) {
2900 /* XXX repeated code */
2901 int src = 0, dst = 0, n = 0;
2902
2903 if (e->command[0] == '_')
2904 continue;
2905
2906 /*
2907 * Try to match words, up to and excluding the last word, which
2908 * is either a blank or something that we want to extend.
2909 */
2910 for (;src < argindex; dst++, src += n) {
2911 n = word_match(argv[src], e->cmda[dst]);
2912 if (n < 0)
2913 break;
2914 }
2915
2916 if (src != argindex && more_words(e->cmda + dst)) /* not a match */
2917 continue;
2918 ret = is_prefix(argv[src], e->cmda[dst], state - matchnum, &n);
2919 matchnum += n; /* this many matches here */
2920 if (ret) {
2921 /*
2922 * argv[src] is a valid prefix of the next word in this
2923 * command. If this is also the correct entry, return it.
2924 */
2925 if (matchnum > state)
2926 break;
2927 ast_free(ret);
2928 ret = NULL;
2929 } else if (ast_strlen_zero(e->cmda[dst])) {
2930 /*
2931 * This entry is a prefix of the command string entered
2932 * (only one entry in the list should have this property).
2933 * Run the generator if one is available. In any case we are done.
2934 */
2935 if (e->handler) { /* new style command */
2936 struct ast_cli_args a = {
2937 .line = matchstr, .word = word,
2938 .pos = argindex,
2939 .n = state - matchnum,
2940 .argv = argv,
2941 .argc = x};
2942
2943 /* If the command is in a module it must be running. */
2944 if (!e->module || ast_module_running_ref(e->module)) {
2945 ret = e->handler(e, CLI_GENERATE, &a);
2947 }
2948 }
2949 if (ret)
2950 break;
2951 }
2952 }
2953 if (lock)
2955 ast_free(duplicate);
2956 return ret;
2957}
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:2269
static int more_words(const char *const *dst)
returns true if there are more words to match
Definition: main/cli.c:2858
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:2308
static struct ast_cli_entry * cli_next(struct ast_cli_entry *e)
Definition: main/cli.c:966
static char * parse_args(const char *s, int *argc, const char *argv[], int max, int *trailingwhitespace)
Definition: main/cli.c:2640
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition: module.h:469
#define NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_join(s, len, w)
Join an array of strings into a single string.
Definition: strings.h:520
const char *const * argv
Definition: cli.h:161
descriptor for a cli entry.
Definition: cli.h:171
char *(* handler)(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: cli.h:187
struct ast_module * module
Definition: cli.h:180
const char *const cmda[AST_MAX_CMD_LEN]
Definition: cli.h:172
char * command
Definition: cli.h:186
static struct test_val a
#define ARRAY_LEN(a)
Definition: utils.h: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 2462 of file main/cli.c.

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

2540{
2541 int i, res = 0;
2542
2543 for (i = 0; i < len; i++) {
2544 res |= __ast_cli_register(e + i, module);
2545 }
2546
2547 return res;
2548}
int __ast_cli_register(struct ast_cli_entry *e, struct ast_module *module)
Definition: main/cli.c:2462

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

2965{
2966 int found = 0;
2967 int i;
2968
2970 for (i = 0; i < AST_VECTOR_SIZE(&shutdown_commands); ++i) {
2971 if (e == AST_VECTOR_GET(&shutdown_commands, i)) {
2972 found = 1;
2973 break;
2974 }
2975 }
2977
2978 return found;
2979}
#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 2245 of file main/cli.c.

2246{
2250}
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:2234
static struct ast_cli_entry cli_cli[]
Definition: main/cli.c:2026
#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 3068 of file main/cli.c.

3069{
3070 int res;
3071
3075
3076 return res;
3077}
#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 2252 of file main/cli.c.

2253{
2256}
static void cli_channels_shutdown(void)
Definition: main/cli.c:2239
static struct ast_cli_entry cli_channels_cli[]
Definition: main/cli.c:2058

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

2982{
2983 const char *args[AST_MAX_ARGS + 1];
2984 struct ast_cli_entry *e = NULL;
2985 int x;
2986 char *duplicate = parse_args(s, &x, args + 1, AST_MAX_ARGS, NULL);
2987 char tmp[AST_MAX_ARGS + 1];
2988 char *retval = CLI_FAILURE;
2989 struct ast_cli_args a = {
2990 .fd = fd, .argc = x, .argv = args+1 };
2991
2992 if (duplicate == NULL)
2993 return RESULT_FAILURE;
2994
2995 if (x < 1) /* We need at least one entry, otherwise ignore */
2996 goto done;
2997
2999 e = find_cli(args + 1, 0);
3000 if (e)
3003 if (e == NULL) {
3004 ast_cli(fd, "No such command '%s' (type 'core show help %s' for other possible commands)\n", s, find_best(args + 1));
3005 goto done;
3006 }
3007
3009 ast_cli(fd, "Command '%s' cannot be run during shutdown\n", s);
3010 goto done;
3011 }
3012
3013 ast_join(tmp, sizeof(tmp), args + 1);
3014 /* Check if the user has rights to run this command. */
3015 if (!cli_has_permissions(uid, gid, tmp)) {
3016 ast_cli(fd, "You don't have permissions to run '%s' command\n", tmp);
3017 goto done;
3018 }
3019
3020 /*
3021 * Within the handler, argv[-1] contains a pointer to the ast_cli_entry.
3022 * Remember that the array returned by parse_args is NULL-terminated.
3023 */
3024 args[0] = (char *)e;
3025
3026 /* If the command is in a module it must be running. */
3027 if (!e->module || ast_module_running_ref(e->module)) {
3028 retval = e->handler(e, CLI_HANDLER, &a);
3030 }
3031
3032 if (retval == CLI_SHOWUSAGE) {
3033 ast_cli(fd, "%s", S_OR(e->usage, "Invalid usage, but no usage information available.\n"));
3034 } else if (retval == CLI_FAILURE) {
3035 ast_cli(fd, "Command '%s' failed.\n", s);
3036 }
3037
3038done:
3039 if (e) {
3041 }
3042 ast_free(duplicate);
3044}
int ast_shutting_down(void)
Definition: asterisk.c:1873
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:2402
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:2964
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 3046 of file main/cli.c.

3047{
3048 char cmd[512];
3049 int x, y = 0, count = 0;
3050
3051 for (x = 0; x < size; x++) {
3052 cmd[y] = s[x];
3053 y++;
3054 if (s[x] == '\0') {
3055 ast_cli_command_full(uid, gid, fd, cmd);
3056 y = 0;
3057 count++;
3058 }
3059 }
3060 return count;
3061}
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:2981

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

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

1854{
1855 int i, which = 0, len;
1856 len = ast_strlen_zero(word) ? 0 : strlen(word);
1857
1858 for (i = 0; choices[i]; i++) {
1859 if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state) {
1860 if (state != -1) {
1861 return ast_strdup(choices[i]);
1862 }
1863
1864 if (ast_cli_completion_add(ast_strdup(choices[i]))) {
1865 return NULL;
1866 }
1867 }
1868 }
1869 return NULL;
1870}
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2768

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

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

◆ ast_cli_completion_add()

int ast_cli_completion_add ( char *  value)

Add a result to a request for completion options.

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

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

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

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

2769{
2770 return cli_completion_vector_add(ast_threadstorage_get_ptr(&completion_storage), value);
2771}
static int cli_completion_vector_add(struct ast_vector_string *vec, char *value)
Definition: main/cli.c:2747
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 2712 of file main/cli.c.

2713{
2715 char **match_list;
2716
2717 if (!vec) {
2718 return NULL;
2719 }
2720
2721 if (AST_VECTOR_APPEND(vec, NULL)) {
2722 /* We failed to NULL terminate the elements */
2725
2726 return NULL;
2727 }
2728
2729 match_list = AST_VECTOR_STEAL_ELEMENTS(vec);
2731
2732 return match_list;
2733}
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:2773
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 2773 of file main/cli.c.

2774{
2775 char *retstr, *prevstr;
2776 size_t max_equal;
2777 size_t which = 0;
2778 struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec));
2779
2780 /* Recursion into this function is a coding error. */
2781 ast_assert(!ast_threadstorage_get_ptr(&completion_storage));
2782
2783 if (!vec) {
2784 return NULL;
2785 }
2786
2787 if (ast_threadstorage_set_ptr(&completion_storage, vec)) {
2788 ast_log(LOG_ERROR, "Failed to initialize threadstorage for completion.\n");
2789 ast_free(vec);
2790
2791 return NULL;
2792 }
2793
2794 while ((retstr = ast_cli_generator(text, word, which)) != NULL) {
2795 if (cli_completion_vector_add(vec, retstr)) {
2796 ast_threadstorage_set_ptr(&completion_storage, NULL);
2797
2798 goto vector_cleanup;
2799 }
2800
2801 ++which;
2802 }
2803
2804 ast_threadstorage_set_ptr(&completion_storage, NULL);
2805
2806 if (!AST_VECTOR_SIZE(vec)) {
2808
2809 return NULL;
2810 }
2811
2812 prevstr = AST_VECTOR_GET(vec, 0);
2813 max_equal = strlen(prevstr);
2814 which = 1;
2815
2816 /* Find the longest substring that is common to all results
2817 * (it is a candidate for completion), and store a copy in entry 0.
2818 */
2819 while (which < AST_VECTOR_SIZE(vec)) {
2820 size_t i = 0;
2821
2822 retstr = AST_VECTOR_GET(vec, which);
2823 /* Check for and remove duplicate strings. */
2824 if (!strcasecmp(prevstr, retstr)) {
2825 AST_VECTOR_REMOVE(vec, which, 1);
2826 ast_free(retstr);
2827
2828 continue;
2829 }
2830
2831 while (i < max_equal && toupper(prevstr[i]) == toupper(retstr[i])) {
2832 i++;
2833 }
2834
2835 max_equal = i;
2836 prevstr = retstr;
2837 ++which;
2838 }
2839
2840 /* Insert longest match to position 0. */
2841 retstr = ast_strndup(AST_VECTOR_GET(vec, 0), max_equal);
2842 if (!retstr || AST_VECTOR_INSERT_AT(vec, 0, retstr)) {
2843 ast_free(retstr);
2844
2845 goto vector_cleanup;
2846 }
2847
2848 return vec;
2849
2850vector_cleanup:
2853
2854 return NULL;
2855}
#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:2959
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 2959 of file main/cli.c.

2960{
2961 return __ast_cli_generator(text, word, state, 1);
2962}
static char * __ast_cli_generator(const char *text, const char *word, int state, int lock)
Definition: main/cli.c:2871

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

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

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

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

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

◆ ast_cli_unregister()

int ast_cli_unregister ( struct ast_cli_entry e)

Unregisters a command or an array of commands.

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

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

2440{
2441 if (e->inuse) {
2442 ast_log(LOG_WARNING, "Can't remove command that is in use\n");
2443 } else {
2445 AST_RWLIST_REMOVE(&helpers, e, list);
2448 ast_free(e->_full_cmd);
2449 e->_full_cmd = NULL;
2450 if (e->handler) {
2451 /* this is a new-style entry. Reset fields and free memory. */
2452 char *cmda = (char *) e->cmda;
2453 memset(cmda, '\0', sizeof(e->cmda));
2454 ast_free(e->command);
2455 e->command = NULL;
2456 e->usage = NULL;
2457 }
2458 }
2459 return 0;
2460}
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:885
static void remove_shutdown_command(struct ast_cli_entry *e)
Definition: main/cli.c:2432

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

2551{
2552 int i, res = 0;
2553
2554 for (i = 0; i < len; i++)
2555 res |= ast_cli_unregister(e + i);
2556
2557 return res;
2558}
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
Definition: main/cli.c:2439

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

1873{
1874 int wordlen = strlen(word), which = 0;
1875 struct ao2_container *cached_channels;
1876 char *ret = NULL;
1877 struct ao2_iterator iter;
1878 struct ast_channel_snapshot *snapshot;
1879
1880 if (pos != rpos) {
1881 return NULL;
1882 }
1883
1884 cached_channels = ast_channel_cache_all();
1885
1886 iter = ao2_iterator_init(cached_channels, 0);
1887 for (; (snapshot = ao2_iterator_next(&iter)); ao2_ref(snapshot, -1)) {
1888 if (!strncasecmp(word, snapshot->base->name, wordlen) && (++which > state)) {
1889 if (state != -1) {
1890 ret = ast_strdup(snapshot->base->name);
1891 ao2_ref(snapshot, -1);
1892 break;
1893 }
1894
1895 if (ast_cli_completion_add(ast_strdup(snapshot->base->name))) {
1896 ao2_ref(snapshot, -1);
1897 break;
1898 }
1899 }
1900 }
1901 ao2_iterator_destroy(&iter);
1902 ao2_ref(cached_channels, -1);
1903
1904 return ret;
1905}
#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 cli_complete_notify(), handle_cli_agi_add_cmd(), handle_cli_mixmonitor(), handle_core_set_debug_channel(), handle_dump_frames(), handle_redirect(), handle_remb_set(), handle_set_chanvar(), handle_show_chanvar(), handle_show_hangup_channel(), handle_showchan(), and handle_softhangup().

◆ ast_debug_get_by_module()

unsigned int ast_debug_get_by_module ( const char *  module)

Get the debug level for a module.

Parameters
modulethe name of module
Returns
the debug level

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

137{
138 struct module_level *ml;
139 unsigned int res = 0;
140
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 1487 of file main/cli.c.

1488{
1489 struct ast_channel *chan = obj;
1490 struct channel_set_debug_args *args = data;
1491
1492 ast_channel_lock(chan);
1493
1494 if (!(ast_channel_fin(chan) & DEBUGCHAN_FLAG) || !(ast_channel_fout(chan) & DEBUGCHAN_FLAG)) {
1495 if (args->is_off) {
1498 } else {
1501 }
1502 ast_cli(args->fd, "Debugging %s on channel %s\n", args->is_off ? "disabled" : "enabled",
1503 ast_channel_name(chan));
1504 }
1505
1506 ast_channel_unlock(chan);
1507
1508 return 0;
1509}
const char * ast_channel_name(const struct ast_channel *chan)
#define DEBUGCHAN_FLAG
Definition: channel.h:877
unsigned int ast_channel_fin(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2968
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:2969
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 2239 of file main/cli.c.

2240{
2242}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: main/cli.c:2550

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

2748{
2749 if (!value) {
2750 return 0;
2751 }
2752
2753 if (!vec || AST_VECTOR_ADD_SORTED(vec, value, strcasecmp)) {
2754 if (vec) {
2755 ast_threadstorage_set_ptr(&completion_storage, NULL);
2756
2758 AST_VECTOR_FREE(vec);
2759 }
2760 ast_free(value);
2761
2762 return -1;
2763 }
2764
2765 return 0;
2766}
#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 2420 of file main/cli.c.

2421{
2422 struct ast_cli_entry *cur = NULL;
2423
2424 while ((cur = cli_next(cur))) {
2425 if (cur == e) {
2426 return 1;
2427 }
2428 }
2429 return 0;
2430}

References cli_next(), and NULL.

Referenced by __ast_cli_register().

◆ cli_next()

static struct ast_cli_entry * cli_next ( struct ast_cli_entry e)
static

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

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

References AST_LIST_FIRST, AST_LIST_NEXT, and ast_cli_entry::list.

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

◆ cli_shutdown()

static void cli_shutdown ( void  )
static

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

2097{
2098 struct cli_perm *perm;
2099 struct usergroup_cli_perm *user_perm;
2100
2102 while ((user_perm = AST_LIST_REMOVE_HEAD(&cli_perms, list))) {
2103 while ((perm = AST_LIST_REMOVE_HEAD(user_perm->perms, list))) {
2104 ast_free(perm->command);
2105 ast_free(perm);
2106 }
2107 ast_free(user_perm);
2108 }
2110}
#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 2402 of file main/cli.c.

2403{
2404 static char cmdline[80];
2405 int x;
2406 /* See how close we get, then print the candidate */
2407 const char *myargv[AST_MAX_CMD_LEN] = { NULL, };
2408
2410 for (x = 0; argv[x]; x++) {
2411 myargv[x] = argv[x];
2412 if (!find_cli(myargv, -1))
2413 break;
2414 }
2416 ast_join(cmdline, sizeof(cmdline), myargv);
2417 return cmdline;
2418}

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

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

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

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

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

◆ handle_chanlist()

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

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

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

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

References ast_cli_entry::_full_cmd, a, ast_cli(), ast_cli_generator(), ast_join, AST_MAX_ARGS, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, cli_has_permissions(), CLI_INIT, cli_next(), CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, S_OR, ast_cli_entry::summary, 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 1998 of file main/cli.c.

1999{
2000 extern int malloc_trim(size_t __pad) __THROW;
2001
2002 switch (cmd) {
2003 case CLI_INIT:
2004 e->command = "malloc trim";
2005 e->usage =
2006 "Usage: malloc trim\n"
2007 " Try to give excess memory back to the OS.\n";
2008 return NULL;
2009 case CLI_GENERATE:
2010 return NULL;
2011 }
2012
2013 if (malloc_trim(0)) {
2014 ast_cli(a->fd, "Returned some memory to the OS.\n");
2015 } else {
2016 ast_cli(a->fd, "No memory returned to the OS.\n");
2017 }
2018
2019 return CLI_SUCCESS;
2020}

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

◆ handle_cli_reload_permissions()

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

handles CLI command 'cli reload permissions'

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

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

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

◆ handle_cli_show_permissions()

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

handles CLI command 'cli show permissions'

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

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

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

◆ handle_cli_wait_fullybooted()

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

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

1962{
1963 switch (cmd) {
1964 case CLI_INIT:
1965 e->command = "core waitfullybooted";
1966 e->usage =
1967 "Usage: core waitfullybooted\n"
1968 " Wait until Asterisk has fully booted.\n";
1969 return NULL;
1970 case CLI_GENERATE:
1971 return NULL;
1972 }
1973
1975 usleep(100);
1976 }
1977
1978 ast_cli(a->fd, "Asterisk has fully booted.\n");
1979
1980 return CLI_SUCCESS;
1981}
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 1428 of file main/cli.c.

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

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

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

◆ handle_core_set_debug_channel()

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

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

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

1578{
1579 const char *argv4 = a->argv ? S_OR(a->argv[4], "") : "";
1580 int offset = strncasecmp(argv4, "off", strlen(argv4)) ? 0 : 1;
1581
1582 switch (cmd) {
1583 case CLI_INIT:
1584 e->command = "core set debug category";
1585 e->usage =
1586 "Usage: core set debug category <category>[:<sublevel>] [category[:<sublevel] ...]\n"
1587 " core set debug category off [<category> [<category>] ...]\n\n"
1588 " Allows enabling and disabling debug logging categories.\n"
1589 " When a category is enabled all relevant debug messages are logged\n"
1590 " for a given category. However, if a sublevel is specified only\n"
1591 " those categorized messages at or below the coded debug sublevel\n"
1592 " are logged.\n";
1593 return NULL;
1594
1595 case CLI_GENERATE:
1596 if (a->pos < e->args) {
1597 return NULL;
1598 }
1599
1600 if (a->pos == 4 && offset) {
1602 }
1603
1604 return ast_debug_category_complete(a->argv + 4,
1605 a->pos - e->args, a->word, a->n - 1);
1606 }
1607
1608 if (a->argc <= e->args) {
1609 return CLI_SHOWUSAGE;
1610 }
1611
1612 ast_debug_category_set_sublevels(a->argv + e->args + offset, a->argc - e->args - offset,
1614
1615 return CLI_SUCCESS;
1616}
#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 2594 of file main/cli.c.

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

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:1978
@ 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:1271

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

◆ handle_modlist()

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

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

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

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

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

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

◆ handle_reload()

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

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

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

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

◆ handle_showcalls()

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

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

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

1646{
1647 struct ast_channel *chan;
1648 struct timeval now;
1649 char cdrtime[256];
1650 struct ast_str *obuf;/*!< Buffer for CDR variables. */
1651 struct ast_str *output;/*!< Accumulation buffer for all output. */
1652 long elapsed_seconds=0;
1653 int hour=0, min=0, sec=0;
1654 struct ast_var_t *var;
1655 struct ast_str *write_transpath = ast_str_alloca(256);
1656 struct ast_str *read_transpath = ast_str_alloca(256);
1657 struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1658 struct ast_bridge *bridge;
1660 char callid_buf[32];
1661 int stream_num;
1662 RAII_VAR(char *, tenant_id, NULL, ast_free);
1663
1664 switch (cmd) {
1665 case CLI_INIT:
1666 e->command = "core show channel";
1667 e->usage =
1668 "Usage: core show channel <channel>\n"
1669 " Shows lots of information about the specified channel.\n";
1670 return NULL;
1671 case CLI_GENERATE:
1672 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
1673 }
1674
1675 if (a->argc != 4) {
1676 return CLI_SHOWUSAGE;
1677 }
1678
1679 obuf = ast_str_thread_get(&ast_str_thread_global_buf, 16);
1680 if (!obuf) {
1681 return CLI_FAILURE;
1682 }
1683
1684 chan = ast_channel_get_by_name(a->argv[3]);
1685 if (!chan) {
1686 ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
1687
1688 return CLI_SUCCESS;
1689 }
1690
1691 output = ast_str_create(8192);
1692 if (!output) {
1693 ast_channel_unref(chan);
1694
1695 return CLI_FAILURE;
1696 }
1697
1698 now = ast_tvnow();
1699 ast_channel_lock(chan);
1700
1702 elapsed_seconds = now.tv_sec - ast_channel_creationtime(chan).tv_sec;
1703 hour = elapsed_seconds / 3600;
1704 min = (elapsed_seconds % 3600) / 60;
1705 sec = elapsed_seconds % 60;
1706 snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
1707 } else {
1708 strcpy(cdrtime, "N/A");
1709 }
1710
1711 ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath);
1712 ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath);
1713
1714 bridge = ast_channel_get_bridge(chan);
1715 callid_buf[0] = '\0';
1716 callid = ast_channel_callid(chan);
1717 if (callid) {
1718 ast_callid_strnprint(callid_buf, sizeof(callid_buf), callid);
1719 }
1720
1722 ast_asprintf(&tenant_id, " TenantID: %s\n", ast_channel_tenantid(chan));
1723 }
1724
1725 ast_str_append(&output, 0,
1726 " -- General --\n"
1727 " Name: %s\n"
1728 " Type: %s\n"
1729 " UniqueID: %s\n"
1730 " LinkedID: %s\n"
1731 "%s"
1732 " Caller ID: %s\n"
1733 " Caller ID Name: %s\n"
1734 "Connected Line ID: %s\n"
1735 "Connected Line ID Name: %s\n"
1736 "Eff. Connected Line ID: %s\n"
1737 "Eff. Connected Line ID Name: %s\n"
1738 " DNID Digits: %s\n"
1739 " Language: %s\n"
1740 " State: %s (%u)\n"
1741 " NativeFormats: %s\n"
1742 " WriteFormat: %s\n"
1743 " ReadFormat: %s\n"
1744 " WriteTranscode: %s %s\n"
1745 " ReadTranscode: %s %s\n"
1746 " Time to Hangup: %ld\n"
1747 " Elapsed Time: %s\n"
1748 " Bridge ID: %s\n"
1749 " -- PBX --\n"
1750 " Context: %s\n"
1751 " Extension: %s\n"
1752 " Priority: %d\n"
1753 " Call Group: %llu\n"
1754 " Pickup Group: %llu\n"
1755 " Application: %s\n"
1756 " Data: %s\n"
1757 " Call Identifer: %s\n",
1758 ast_channel_name(chan),
1759 ast_channel_tech(chan)->type,
1762 !ast_strlen_zero(tenant_id) ? tenant_id : "",
1763 S_COR(ast_channel_caller(chan)->id.number.valid,
1764 ast_channel_caller(chan)->id.number.str, "(N/A)"),
1765 S_COR(ast_channel_caller(chan)->id.name.valid,
1766 ast_channel_caller(chan)->id.name.str, "(N/A)"),
1767 S_COR(ast_channel_connected(chan)->id.number.valid,
1768 ast_channel_connected(chan)->id.number.str, "(N/A)"),
1769 S_COR(ast_channel_connected(chan)->id.name.valid,
1770 ast_channel_connected(chan)->id.name.str, "(N/A)"),
1772 ast_channel_connected_effective_id(chan).number.str, "(N/A)"),
1774 ast_channel_connected_effective_id(chan).name.str, "(N/A)"),
1775 S_OR(ast_channel_dialed(chan)->number.str, "(N/A)"),
1778 ast_channel_state(chan),
1782 ast_str_strlen(write_transpath) ? "Yes" : "No",
1783 ast_str_buffer(write_transpath),
1784 ast_str_strlen(read_transpath) ? "Yes" : "No",
1785 ast_str_buffer(read_transpath),
1786 (long)ast_channel_whentohangup(chan)->tv_sec,
1787 cdrtime,
1788 bridge ? bridge->uniqueid : "(Not bridged)",
1789 ast_channel_context(chan),
1790 ast_channel_exten(chan),
1794 S_OR(ast_channel_appl(chan), "(N/A)"),
1795 S_OR(ast_channel_data(chan), "(Empty)"),
1796 S_OR(callid_buf, "(None)")
1797 );
1798
1799 ast_str_append(&output, 0, " Variables:\n");
1800
1801 AST_LIST_TRAVERSE(ast_channel_varshead(chan), var, entries) {
1802 ast_str_append(&output, 0, "%s=%s\n", ast_var_name(var), ast_var_value(var));
1803 }
1804
1805 if (!(ast_channel_tech(chan)->properties & AST_CHAN_TP_INTERNAL)
1806 && ast_cdr_serialize_variables(ast_channel_name(chan), &obuf, '=', '\n')) {
1807 ast_str_append(&output, 0, " CDR Variables:\n%s\n", ast_str_buffer(obuf));
1808 }
1809
1810 ast_str_append(&output, 0, " -- Streams --\n");
1811 for (stream_num = 0; stream_num < ast_stream_topology_get_count(ast_channel_get_stream_topology(chan)); stream_num++) {
1813 struct ast_variable *metadata = ast_stream_get_metadata_list(stream);
1814
1815 ast_str_append(&output, 0,
1816 "Name: %s\n"
1817 " Type: %s\n"
1818 " State: %s\n"
1819 " Group: %d\n"
1820 " Formats: %s\n"
1821 " Metadata:\n",
1822 ast_stream_get_name(stream),
1825 ast_stream_get_group(stream),
1827 );
1828
1829 if (metadata) {
1830 struct ast_variable *v;
1831 for(v = metadata; v; v = v->next) {
1832 ast_str_append(&output, 0, " %s: %s\n", v->name, v->value);
1833 }
1834 ast_variables_destroy(metadata);
1835 }
1836 }
1837
1838 ast_channel_unlock(chan);
1839
1840 ast_cli(a->fd, "%s", ast_str_buffer(output));
1841 ast_free(output);
1842
1843 ao2_cleanup(bridge);
1844 ast_channel_unref(chan);
1845
1846 return CLI_SUCCESS;
1847}
#define var
Definition: ast_expr2f.c:605
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep)
Serializes all the data and variables for a current CDR record.
Definition: cdr.c:3432
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:991
const char * ast_channel_data(const struct ast_channel *chan)
struct varshead * ast_channel_varshead(struct ast_channel *chan)
const char * ast_channel_tenantid(const struct ast_channel *chan)
struct ast_trans_pvt * ast_channel_readtrans(const struct ast_channel *chan)
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
struct ast_trans_pvt * ast_channel_writetrans(const struct ast_channel *chan)
ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
ast_callid ast_channel_callid(const struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
const char * ast_channel_appl(const struct ast_channel *chan)
struct timeval ast_channel_creationtime(struct ast_channel *chan)
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
Definition: channel.c:10553
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:2288
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
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

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

◆ handle_showuptime()

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

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

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

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

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

◆ handle_trace()

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

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

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

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

◆ handle_unload()

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

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

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

2565{
2566 char matchstr[80] = "";
2567 struct ast_cli_entry *e = NULL;
2568 int len = 0;
2569 int found = 0;
2570
2571 if (match) {
2572 ast_join(matchstr, sizeof(matchstr), match);
2573 len = strlen(matchstr);
2574 }
2575 if (!locked)
2577 while ( (e = cli_next(e)) ) {
2578 /* Hide commands that start with '_' */
2579 if (e->_full_cmd[0] == '_')
2580 continue;
2581 if (match && strncasecmp(matchstr, e->_full_cmd, len))
2582 continue;
2583 ast_cli(fd, "%-30s -- %s\n", e->_full_cmd,
2584 S_OR(e->summary, "<no description available>"));
2585 found++;
2586 }
2587 if (!locked)
2589 if (!found && matchstr[0])
2590 ast_cli(fd, "No such command '%s'.\n", matchstr);
2591 return CLI_SUCCESS;
2592}
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 2308 of file main/cli.c.

2310{
2311 int lw;
2312 char *s, *t1;
2313
2314 *actual = 0;
2315 if (ast_strlen_zero(token))
2316 return NULL;
2317 if (ast_strlen_zero(word))
2318 word = ""; /* dummy */
2319 lw = strlen(word);
2320 if (strcspn(word, cli_rsvd) != lw)
2321 return NULL; /* no match if word has reserved chars */
2322 if (strchr(cli_rsvd, token[0]) == NULL) { /* regular match */
2323 if (strncasecmp(token, word, lw)) /* no match */
2324 return NULL;
2325 *actual = 1;
2326 return (pos != 0) ? NULL : ast_strdup(token);
2327 }
2328 /* now handle regexp match */
2329
2330 /* Wildcard always matches, so we never do is_prefix on them */
2331
2332 t1 = ast_strdupa(token + 1); /* copy, skipping first char */
2333 while (pos >= 0 && (s = strsep(&t1, cli_rsvd)) && *s) {
2334 if (*s == '%') /* wildcard */
2335 continue;
2336 if (strncasecmp(s, word, lw)) /* no match */
2337 continue;
2338 (*actual)++;
2339 if (pos-- == 0)
2340 return ast_strdup(s);
2341 }
2342 return NULL;
2343}
char * strsep(char **str, const char *delims)
static const char cli_rsvd[]
Definition: main/cli.c:2071

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

Referenced by __ast_cli_generator().

◆ modlist_modentry()

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

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

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

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

2859{
2860 int i;
2861 for (i = 0; dst[i]; i++) {
2862 if (dst[i][0] != '[')
2863 return -1;
2864 }
2865 return 0;
2866}

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

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

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

Referenced by __ast_cli_generator(), and ast_cli_command_full().

◆ print_uptimestr()

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

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

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

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

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

◆ remove_shutdown_command()

static void remove_shutdown_command ( struct ast_cli_entry e)
static

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

2433{
2437}
#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 2077 of file main/cli.c.

2078{
2079 int i;
2080 char buf[80];
2081
2082 ast_join(buf, sizeof(buf), e->cmda);
2083 e->_full_cmd = ast_strdup(buf);
2084 if (!e->_full_cmd) {
2085 ast_log(LOG_WARNING, "-- cannot allocate <%s>\n", buf);
2086 return -1;
2087 }
2088 e->cmdlen = strcspn(e->_full_cmd, cli_rsvd);
2089 for (i = 0; e->cmda[i]; i++)
2090 ;
2091 e->args = i;
2092 return 0;
2093}

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

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

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 2058 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 2026 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 2071 of file main/cli.c.

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

◆ climodentryfd

int climodentryfd = -1
static

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

Referenced by handle_modlist(), and modlist_modentry().

◆ climodentrylock

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

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

Referenced by handle_modlist().

◆ current

size_t current

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