Asterisk - The Open Source Telephony Project GIT-master-4f2b068
Loading...
Searching...
No Matches
Data Structures | Macros | Functions | Variables
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 <fnmatch.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 arg_looks_like_glob(n)    (strcspn(n, "?*[") < strlen(n))
 
#define arg_looks_like_regex(n)    (*n == '/' && n[strlen(n) - 1] == '/')
 
#define AST_CLI_INITLEN   256
 Initial buffer size for resulting strings in ast_cli()
 
#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 MAX_REGEX_ERROR_LEN   128
 
#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 int allowed_on_shutdown (struct ast_cli_entry *e)
 
void ast_builtins_init (void)
 initialize the _full_cmd string in * each of the builtins.
 
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.
 
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.
 
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.
 
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.
 
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.
 
struct ast_vector_stringast_cli_completion_vector (const char *text, const char *word)
 Generates a vector of strings for CLI completion.
 
char * ast_cli_generator (const char *text, const char *word, int state)
 Readline madness Useful for readline, that's about it.
 
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)
 
int ast_cli_unregister (struct ast_cli_entry *e)
 Unregisters a command or an array of commands.
 
int ast_cli_unregister_multiple (struct ast_cli_entry *e, int len)
 Unregister multiple commands.
 
char * ast_complete_channels (const char *line, const char *word, int pos, int state, int rpos)
 Command completion for the list of active channels.
 
unsigned int ast_debug_get_by_module (const char *module)
 Get the debug level for a module.
 
 AST_THREADSTORAGE_CUSTOM_SCOPE (ast_cli_buf, NULL, ast_free_ptr, static)
 
 AST_THREADSTORAGE_RAW (completion_storage)
 
unsigned int ast_trace_get_by_module (const char *module)
 Get the trace level for a module.
 
static int channel_hangup_matches (struct ast_cli_args *a, int(*matchfn)(const char *, const void *), const void *data)
 
static int channel_match_by_glob (const char *channel_name, const void *pattern)
 
static int channel_match_by_regex (const char *channel_name, const void *data)
 
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.
 
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.
 
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'
 
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'
 
static char * handle_cli_show_permissions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handles CLI command 'cli show permissions'
 
static char * handle_cli_wait_fullybooted (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_commandmatchesarray (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_core_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_core_set_debug_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_debug_category (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_debug_or_trace (int handler, struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_help (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_load (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_logger_mute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_modlist (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_refresh (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_showcalls (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_showchan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_showuptime (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_softhangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_trace (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_unload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_verbose (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * help1 (int fd, const char *const match[], int locked)
 helper for final part of handle_help if locked = 1, assume the list is already locked
 
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.
 
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
 
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_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.
 
static struct cli_perms cli_perms = AST_RWLIST_HEAD_INIT_VALUE
 
static const char cli_rsvd [] = "[]{}|*%"
 
static int climodentryfd = -1
 
static ast_mutex_t climodentrylock = AST_MUTEX_INIT_VALUE
 
static struct module_level_list debug_modules = AST_RWLIST_HEAD_INIT_VALUE
 
static struct helpers helpers = AST_RWLIST_HEAD_INIT_VALUE
 
static const char perms_config [] = "cli_permissions.conf"
 CLI permissions config file.
 
static ast_mutex_t permsconfiglock = AST_MUTEX_INIT_VALUE
 mutex used to prevent a user from running the 'cli reload permissions' command while it is already running.
 
struct { 
 
   size_t   current 
 
   struct ast_cli_entry **   elems 
 
   size_t   max 
 
shutdown_commands 
 
static ast_rwlock_t shutdown_commands_lock = AST_RWLOCK_INIT_VALUE
 
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

◆ arg_looks_like_glob

#define arg_looks_like_glob (   n)     (strcspn(n, "?*[") < strlen(n))

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

◆ arg_looks_like_regex

#define arg_looks_like_regex (   n)     (*n == '/' && n[strlen(n) - 1] == '/')

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

◆ AST_CLI_INITLEN

#define AST_CLI_INITLEN   256

Initial buffer size for resulting strings in ast_cli()

Definition at line 117 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 406 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)

◆ MAX_REGEX_ERROR_LEN

#define MAX_REGEX_ERROR_LEN   128

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

◆ MINUTE

#define MINUTE   (SECOND*60)

◆ MODLIST_FORMAT

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

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

◆ MODLIST_FORMAT2

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

Definition at line 898 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 407 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 408 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 2948 of file main/cli.c.

2949{
2950 const char *argv[AST_MAX_ARGS];
2951 struct ast_cli_entry *e = NULL;
2952 int x = 0, argindex, matchlen;
2953 int matchnum=0;
2954 char *ret = NULL;
2955 char matchstr[80] = "";
2956 int tws = 0;
2957 /* Split the argument into an array of words */
2958 char *duplicate = parse_args(text, &x, argv, ARRAY_LEN(argv), &tws);
2959
2960 if (!duplicate) /* malloc error */
2961 return NULL;
2962
2963 /* Compute the index of the last argument (could be an empty string) */
2964 argindex = (!ast_strlen_zero(word) && x>0) ? x-1 : x;
2965
2966 /* rebuild the command, ignore terminating white space and flatten space */
2967 ast_join(matchstr, sizeof(matchstr)-1, argv);
2968 matchlen = strlen(matchstr);
2969 if (tws) {
2970 strcat(matchstr, " "); /* XXX */
2971 if (matchlen)
2972 matchlen++;
2973 }
2974 if (lock)
2976 while ( (e = cli_next(e)) ) {
2977 /* XXX repeated code */
2978 int src = 0, dst = 0, n = 0;
2979
2980 if (e->command[0] == '_')
2981 continue;
2982
2983 /*
2984 * Try to match words, up to and excluding the last word, which
2985 * is either a blank or something that we want to extend.
2986 */
2987 for (;src < argindex; dst++, src += n) {
2988 n = word_match(argv[src], e->cmda[dst]);
2989 if (n < 0)
2990 break;
2991 }
2992
2993 if (src != argindex && more_words(e->cmda + dst)) /* not a match */
2994 continue;
2995 ret = is_prefix(argv[src], e->cmda[dst], state - matchnum, &n);
2996 matchnum += n; /* this many matches here */
2997 if (ret) {
2998 /*
2999 * argv[src] is a valid prefix of the next word in this
3000 * command. If this is also the correct entry, return it.
3001 */
3002 if (matchnum > state)
3003 break;
3004 ast_free(ret);
3005 ret = NULL;
3006 } else if (ast_strlen_zero(e->cmda[dst])) {
3007 /*
3008 * This entry is a prefix of the command string entered
3009 * (only one entry in the list should have this property).
3010 * Run the generator if one is available. In any case we are done.
3011 */
3012 if (e->handler) { /* new style command */
3013 struct ast_cli_args a = {
3014 .line = matchstr, .word = word,
3015 .pos = argindex,
3016 .n = state - matchnum,
3017 .argv = argv,
3018 .argc = x};
3019
3020 /* If the command is in a module it must be running. */
3021 if (!e->module || ast_module_running_ref(e->module)) {
3022 ret = e->handler(e, CLI_GENERATE, &a);
3023 ast_module_unref(e->module);
3024 }
3025 }
3026 if (ret)
3027 break;
3028 }
3029 }
3030 if (lock)
3032 ast_free(duplicate);
3033 return ret;
3034}
ast_mutex_t lock
Definition app_sla.c:337
#define ast_free(a)
Definition astmm.h:180
#define AST_MAX_ARGS
Definition cli.h:50
@ CLI_GENERATE
Definition cli.h:153
short word
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition linkedlists.h:78
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
static int word_match(const char *cmd, const char *cli_word)
Definition main/cli.c:2346
static int more_words(const char *const *dst)
returns true if there are more words to match
Definition main/cli.c:2935
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:2385
static struct ast_cli_entry * cli_next(struct ast_cli_entry *e)
Definition main/cli.c:969
static char * parse_args(const char *s, int *argc, const char *argv[], int max, int *trailingwhitespace)
Definition main/cli.c:2717
#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
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:706

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

2540{
2541 struct ast_cli_entry *cur;
2542 int i, lf, ret = -1;
2543
2544 struct ast_cli_args a; /* fake argument */
2545 char **dst = (char **)e->cmda; /* need to cast as the entry is readonly */
2546 char *s;
2547
2549
2550 if (cli_is_registered(e)) {
2551 ast_log(LOG_WARNING, "Command '%s' already registered (the same ast_cli_entry)\n",
2552 S_OR(e->_full_cmd, e->command));
2553 ret = 0; /* report success */
2554 goto done;
2555 }
2556
2557 memset(&a, '\0', sizeof(a));
2558
2559 e->module = module;
2560 /* No module reference needed here, the module called us. */
2561 e->handler(e, CLI_INIT, &a);
2562
2563 /* XXX check that usage and command are filled up */
2564 s = ast_skip_blanks(e->command);
2565 s = e->command = ast_strdup(s);
2566 for (i=0; !ast_strlen_zero(s) && i < AST_MAX_CMD_LEN-1; i++) {
2567 *dst++ = s; /* store string */
2568 s = ast_skip_nonblanks(s);
2569 if (*s == '\0') /* we are done */
2570 break;
2571 *s++ = '\0';
2572 s = ast_skip_blanks(s);
2573 }
2574 *dst++ = NULL;
2575
2576 if (find_cli(e->cmda, 1)) {
2577 ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n",
2578 S_OR(e->_full_cmd, e->command));
2579 goto done;
2580 }
2581 if (set_full_cmd(e)) {
2582 ast_log(LOG_WARNING, "Error registering CLI Command '%s'\n",
2583 S_OR(e->_full_cmd, e->command));
2584 goto done;
2585 }
2586
2587 lf = e->cmdlen;
2589 int len = cur->cmdlen;
2590 if (lf < len)
2591 len = lf;
2592 if (strncasecmp(e->_full_cmd, cur->_full_cmd, len) < 0) {
2594 break;
2595 }
2596 }
2598
2599 if (!cur)
2601 ret = 0; /* success */
2602
2603done:
2605 if (ret) {
2606 ast_free(e->command);
2607 e->command = NULL;
2608 }
2609
2610 return ret;
2611}
#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
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition linkedlists.h:52
#define AST_RWLIST_TRAVERSE_SAFE_END
#define AST_RWLIST_INSERT_TAIL
#define AST_RWLIST_INSERT_BEFORE_CURRENT
static struct ast_cli_entry * find_cli(const char *const cmds[], int match_type)
Definition main/cli.c:2435
static int set_full_cmd(struct ast_cli_entry *e)
Definition main/cli.c:2154
static int cli_is_registered(struct ast_cli_entry *e)
Definition main/cli.c:2497
#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 *attribute_pure ast_skip_nonblanks(const char *str)
Gets a pointer to first whitespace character in a string.
Definition strings.h:204
char *attribute_pure 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
struct ast_module *char * _full_cmd
Definition cli.h:180
int done

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

2617{
2618 int i, res = 0;
2619
2620 for (i = 0; i < len; i++) {
2621 res |= __ast_cli_register(e + i, module);
2622 }
2623
2624 return res;
2625}
int __ast_cli_register(struct ast_cli_entry *e, struct ast_module *module)
Definition main/cli.c:2539

References __ast_cli_register(), and len().

◆ allowed_on_shutdown()

static int allowed_on_shutdown ( struct ast_cli_entry e)
static

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

3042{
3043 int found = 0;
3044 int i;
3045
3047 for (i = 0; i < AST_VECTOR_SIZE(&shutdown_commands); ++i) {
3048 if (e == AST_VECTOR_GET(&shutdown_commands, i)) {
3049 found = 1;
3050 break;
3051 }
3052 }
3054
3055 return found;
3056}
#define ast_rwlock_rdlock(a)
Definition lock.h:242
#define ast_rwlock_unlock(a)
Definition lock.h:241
static ast_rwlock_t shutdown_commands_lock
Definition main/cli.c:113
static struct @355 shutdown_commands
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition vector.h:620
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition vector.h:691

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

Referenced by ast_cli_command_full().

◆ ast_builtins_init()

void ast_builtins_init ( void  )

initialize the _full_cmd string in * each of the builtins.

Provided by cli.c

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

2323{
2327}
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:2311
static struct ast_cli_entry cli_cli[]
Definition main/cli.c:2104
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition vector.h:124

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

Referenced by asterisk_daemon().

◆ ast_cli()

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

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

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

References ast_carefulwrite(), AST_CLI_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_hangup_matches(), 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 3145 of file main/cli.c.

3146{
3147 int res;
3148
3152
3153 return res;
3154}
#define ast_rwlock_wrlock(a)
Definition lock.h:243
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition vector.h:267

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

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

◆ ast_cli_channels_init()

void ast_cli_channels_init ( void  )

Provided by cli.c

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

2330{
2333}
static void cli_channels_shutdown(void)
Definition main/cli.c:2316
static struct ast_cli_entry cli_channels_cli[]
Definition main/cli.c:2136

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

3059{
3060 const char *args[AST_MAX_ARGS + 1];
3061 struct ast_cli_entry *e = NULL;
3062 int x;
3063 char *duplicate = parse_args(s, &x, args + 1, AST_MAX_ARGS, NULL);
3064 char tmp[AST_MAX_ARGS + 1];
3065 char *retval = CLI_FAILURE;
3066 struct ast_cli_args a = {
3067 .fd = fd, .argc = x, .argv = args+1 };
3068
3069 if (duplicate == NULL)
3070 return RESULT_FAILURE;
3071
3072 if (x < 1) /* We need at least one entry, otherwise ignore */
3073 goto done;
3074
3076 e = find_cli(args + 1, 0);
3077 if (e)
3080 if (e == NULL) {
3081 ast_cli(fd, "No such command '%s' (type 'core show help %s' for other possible commands)\n", s, find_best(args + 1));
3082 goto done;
3083 }
3084
3086 ast_cli(fd, "Command '%s' cannot be run during shutdown\n", s);
3087 goto done;
3088 }
3089
3090 ast_join(tmp, sizeof(tmp), args + 1);
3091 /* Check if the user has rights to run this command. */
3092 if (!cli_has_permissions(uid, gid, tmp)) {
3093 ast_cli(fd, "You don't have permissions to run '%s' command\n", tmp);
3094 goto done;
3095 }
3096
3097 /*
3098 * Within the handler, argv[-1] contains a pointer to the ast_cli_entry.
3099 * Remember that the array returned by parse_args is NULL-terminated.
3100 */
3101 args[0] = (char *)e;
3102
3103 /* If the command is in a module it must be running. */
3104 if (!e->module || ast_module_running_ref(e->module)) {
3105 retval = e->handler(e, CLI_HANDLER, &a);
3106 ast_module_unref(e->module);
3107 }
3108
3109 if (retval == CLI_SHOWUSAGE) {
3110 ast_cli(fd, "%s", S_OR(e->usage, "Invalid usage, but no usage information available.\n"));
3111 } else if (retval == CLI_FAILURE) {
3112 ast_cli(fd, "Command '%s' failed.\n", s);
3113 }
3114
3115done:
3116 if (e) {
3118 }
3119 ast_free(duplicate);
3120 return retval == CLI_SUCCESS ? RESULT_SUCCESS : RESULT_FAILURE;
3121}
int ast_shutting_down(void)
Definition asterisk.c:1889
#define CLI_SHOWUSAGE
Definition cli.h:45
#define CLI_SUCCESS
Definition cli.h:44
#define RESULT_SUCCESS
Definition cli.h:40
@ CLI_HANDLER
Definition cli.h:154
#define CLI_FAILURE
Definition cli.h:46
#define RESULT_FAILURE
Definition cli.h:42
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition lock.h:764
static char * find_best(const char *argv[])
Definition main/cli.c:2479
void ast_cli(int fd, const char *fmt,...)
Definition main/cli.c:121
static int allowed_on_shutdown(struct ast_cli_entry *e)
Definition main/cli.c:3041
static int cli_has_permissions(int uid, int gid, const char *command)
Definition main/cli.c:186
static struct @522 args
const int fd
Definition cli.h:159
int inuse
Definition cli.h:179
const char * usage
Definition cli.h:177

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, NULL, parse_args(), RESULT_FAILURE, RESULT_SUCCESS, S_OR, and ast_cli_entry::usage.

Referenced by ast_cli_command_multiple_full().

◆ ast_cli_command_multiple_full()

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

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

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

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

3124{
3125 char cmd[512];
3126 int x, y = 0, count = 0;
3127
3128 for (x = 0; x < size; x++) {
3129 cmd[y] = s[x];
3130 y++;
3131 if (s[x] == '\0') {
3132 ast_cli_command_full(uid, gid, fd, cmd);
3133 y = 0;
3134 count++;
3135 }
3136 }
3137 return count;
3138}
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:3058

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

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

1932{
1933 int i, which = 0, len;
1934 len = ast_strlen_zero(word) ? 0 : strlen(word);
1935
1936 for (i = 0; choices[i]; i++) {
1937 if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state) {
1938 if (state != -1) {
1939 return ast_strdup(choices[i]);
1940 }
1941
1942 if (ast_cli_completion_add(ast_strdup(choices[i]))) {
1943 return NULL;
1944 }
1945 }
1946 }
1947 return NULL;
1948}
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition main/cli.c:2845

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

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

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

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

◆ ast_cli_completion_matches()

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

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

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

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

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

2790{
2792 char **match_list;
2793
2794 if (!vec) {
2795 return NULL;
2796 }
2797
2798 if (AST_VECTOR_APPEND(vec, NULL)) {
2799 /* We failed to NULL terminate the elements */
2802
2803 return NULL;
2804 }
2805
2806 match_list = AST_VECTOR_STEAL_ELEMENTS(vec);
2808
2809 return match_list;
2810}
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:2850
String vector definitions.
Definition vector.h:55
#define AST_VECTOR_STEAL_ELEMENTS(vec)
Steal the elements from a vector and reinitialize.
Definition vector.h:151
#define AST_VECTOR_PTR_FREE(vec)
Deallocates this vector pointer.
Definition vector.h:200
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition vector.h:873

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

Referenced by handle_commandmatchesarray().

◆ ast_cli_completion_vector()

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

Generates a vector of strings for CLI completion.

Parameters
textComplete input being matched.
wordCurrent word being matched

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

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

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

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

2851{
2852 char *retstr, *prevstr;
2853 size_t max_equal;
2854 size_t which = 0;
2855 struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec));
2856
2857 /* Recursion into this function is a coding error. */
2858 ast_assert(!ast_threadstorage_get_ptr(&completion_storage));
2859
2860 if (!vec) {
2861 return NULL;
2862 }
2863
2864 if (ast_threadstorage_set_ptr(&completion_storage, vec)) {
2865 ast_log(LOG_ERROR, "Failed to initialize threadstorage for completion.\n");
2866 ast_free(vec);
2867
2868 return NULL;
2869 }
2870
2871 while ((retstr = ast_cli_generator(text, word, which)) != NULL) {
2872 if (cli_completion_vector_add(vec, retstr)) {
2873 ast_threadstorage_set_ptr(&completion_storage, NULL);
2874
2875 goto vector_cleanup;
2876 }
2877
2878 ++which;
2879 }
2880
2881 ast_threadstorage_set_ptr(&completion_storage, NULL);
2882
2883 if (!AST_VECTOR_SIZE(vec)) {
2885
2886 return NULL;
2887 }
2888
2889 prevstr = AST_VECTOR_GET(vec, 0);
2890 max_equal = strlen(prevstr);
2891 which = 1;
2892
2893 /* Find the longest substring that is common to all results
2894 * (it is a candidate for completion), and store a copy in entry 0.
2895 */
2896 while (which < AST_VECTOR_SIZE(vec)) {
2897 size_t i = 0;
2898
2899 retstr = AST_VECTOR_GET(vec, which);
2900 /* Check for and remove duplicate strings. */
2901 if (!strcasecmp(prevstr, retstr)) {
2902 AST_VECTOR_REMOVE(vec, which, 1);
2903 ast_free(retstr);
2904
2905 continue;
2906 }
2907
2908 while (i < max_equal && toupper(prevstr[i]) == toupper(retstr[i])) {
2909 i++;
2910 }
2911
2912 max_equal = i;
2913 prevstr = retstr;
2914 ++which;
2915 }
2916
2917 /* Insert longest match to position 0. */
2918 retstr = ast_strndup(AST_VECTOR_GET(vec, 0), max_equal);
2919 if (!retstr || AST_VECTOR_INSERT_AT(vec, 0, retstr)) {
2920 ast_free(retstr);
2921
2922 goto vector_cleanup;
2923 }
2924
2925 return vec;
2926
2927vector_cleanup:
2930
2931 return NULL;
2932}
#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:3036
int ast_threadstorage_set_ptr(struct ast_threadstorage *ts, void *ptr)
Set a raw pointer from threadstorage.
#define ast_assert(a)
Definition utils.h:779
#define AST_VECTOR_INSERT_AT(vec, idx, elem)
Insert an element at a specific position in a vector, growing the vector if needed.
Definition vector.h:349
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
Definition vector.h:423

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

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

◆ ast_cli_generator()

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

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

Return values
0on success
-1on failure

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

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

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

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

2190{
2191 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2192 struct ast_config *cfg;
2193 char *cat = NULL;
2194 struct ast_variable *v;
2195 struct usergroup_cli_perm *user_group, *cp_entry;
2196 struct cli_perm *perm = NULL;
2197 struct passwd *pw;
2198 struct group *gr;
2199
2201 ast_log(LOG_NOTICE, "You must wait until last 'cli reload permissions' command finish\n");
2202 return 1;
2203 }
2204
2205 cfg = ast_config_load2(perms_config, "" /* core, can't reload */, config_flags);
2206 if (!cfg) {
2208 return 1;
2209 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2211 return 0;
2212 }
2213
2214 /* free current structures. */
2216
2217 while ((cat = ast_category_browse(cfg, cat))) {
2218 if (!strcasecmp(cat, "general")) {
2219 /* General options */
2220 for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
2221 if (!strcasecmp(v->name, "default_perm")) {
2222 cli_default_perm = (!strcasecmp(v->value, "permit")) ? 1: 0;
2223 }
2224 }
2225 continue;
2226 }
2227
2228 /* users or groups */
2229 gr = NULL, pw = NULL;
2230 if (cat[0] == '@') {
2231 /* This is a group */
2232 gr = getgrnam(&cat[1]);
2233 if (!gr) {
2234 ast_log (LOG_WARNING, "Unknown group '%s'\n", &cat[1]);
2235 continue;
2236 }
2237 } else {
2238 /* This is a user */
2239 pw = getpwnam(cat);
2240 if (!pw) {
2241 ast_log (LOG_WARNING, "Unknown user '%s'\n", cat);
2242 continue;
2243 }
2244 }
2245 user_group = NULL;
2246 /* Check for duplicates */
2248 AST_LIST_TRAVERSE(&cli_perms, cp_entry, list) {
2249 if ((pw && cp_entry->uid == pw->pw_uid) || (gr && cp_entry->gid == gr->gr_gid)) {
2250 /* if it is duplicated, just added this new settings, to
2251 the current list. */
2252 user_group = cp_entry;
2253 break;
2254 }
2255 }
2257
2258 if (!user_group) {
2259 /* alloc space for the new user config. */
2260 user_group = ast_calloc(1, sizeof(*user_group));
2261 if (!user_group) {
2262 continue;
2263 }
2264 user_group->uid = (pw ? pw->pw_uid : -1);
2265 user_group->gid = (gr ? gr->gr_gid : -1);
2266 user_group->perms = ast_calloc(1, sizeof(*user_group->perms));
2267 if (!user_group->perms) {
2268 ast_free(user_group);
2269 continue;
2270 }
2271 }
2272 for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
2273 if (ast_strlen_zero(v->value)) {
2274 /* we need to check this condition cause it could break security. */
2275 ast_log(LOG_WARNING, "Empty permit/deny option in user '%s'\n", cat);
2276 continue;
2277 }
2278 if (!strcasecmp(v->name, "permit")) {
2279 perm = ast_calloc(1, sizeof(*perm));
2280 if (perm) {
2281 perm->permit = 1;
2282 perm->command = ast_strdup(v->value);
2283 }
2284 } else if (!strcasecmp(v->name, "deny")) {
2285 perm = ast_calloc(1, sizeof(*perm));
2286 if (perm) {
2287 perm->permit = 0;
2288 perm->command = ast_strdup(v->value);
2289 }
2290 } else {
2291 /* up to now, only 'permit' and 'deny' are possible values. */
2292 ast_log(LOG_WARNING, "Unknown '%s' option\n", v->name);
2293 continue;
2294 }
2295 if (perm) {
2296 /* Added the permission to the user's list. */
2297 AST_LIST_INSERT_TAIL(user_group->perms, perm, list);
2298 perm = NULL;
2299 }
2300 }
2302 AST_RWLIST_INSERT_TAIL(&cli_perms, user_group, list);
2304 }
2305
2306 ast_config_destroy(cfg);
2308 return 0;
2309}
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition extconf.c:3324
#define CONFIG_STATUS_FILEUNCHANGED
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
@ CONFIG_FLAG_FILEUNCHANGED
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition extconf.c:1213
#define LOG_NOTICE
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define ast_mutex_unlock(a)
Definition lock.h:197
#define ast_mutex_trylock(a)
Definition lock.h:198
static ast_mutex_t permsconfiglock
mutex used to prevent a user from running the 'cli reload permissions' command while it is already ru...
Definition main/cli.c:92
static int cli_default_perm
Default permissions value 1=Permit 0=Deny.
Definition main/cli.c:88
static void destroy_user_perms(void)
cleanup (free) cli_perms linkedlist.
Definition main/cli.c:2173
static const char perms_config[]
CLI permissions config file.
Definition main/cli.c:86
static int reload(void)
Structure used to handle boolean flags.
Definition utils.h:220
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
List of restrictions per user.
Definition main/cli.c:70
unsigned int permit
Definition main/cli.c:71
char * command
Definition main/cli.c:72
List of users and permissions.
Definition main/cli.c:94
list of users to apply restrictions.
Definition main/cli.c:79
struct cli_perm_head * perms
Definition main/cli.c:82

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

3141{
3142 print_uptimestr(fd, ast_tv(seconds, 0), prefix, 0);
3143}
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:916
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 2516 of file main/cli.c.

2517{
2518 if (e->inuse) {
2519 ast_log(LOG_WARNING, "Can't remove command that is in use\n");
2520 } else {
2522 AST_RWLIST_REMOVE(&helpers, e, list);
2525 ast_free(e->_full_cmd);
2526 e->_full_cmd = NULL;
2527 if (e->handler) {
2528 /* this is a new-style entry. Reset fields and free memory. */
2529 char *cmda = (char *) e->cmda;
2530 memset(cmda, '\0', sizeof(e->cmda));
2531 ast_free(e->command);
2532 e->command = NULL;
2533 e->usage = NULL;
2534 }
2535 }
2536 return 0;
2537}
#define AST_RWLIST_REMOVE
static void remove_shutdown_command(struct ast_cli_entry *e)
Definition main/cli.c:2509

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(), unload_module(), unload_module(), unload_module(), 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 2627 of file main/cli.c.

2628{
2629 int i, res = 0;
2630
2631 for (i = 0; i < len; i++)
2632 res |= ast_cli_unregister(e + i);
2633
2634 return res;
2635}
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
Definition main/cli.c:2516

References ast_cli_unregister(), and len().

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

1951{
1952 int wordlen = strlen(word), which = 0;
1953 struct ao2_container *cached_channels;
1954 char *ret = NULL;
1955 struct ao2_iterator iter;
1956 struct ast_channel_snapshot *snapshot;
1957
1958 if (pos != rpos) {
1959 return NULL;
1960 }
1961
1962 cached_channels = ast_channel_cache_all();
1963
1964 iter = ao2_iterator_init(cached_channels, 0);
1965 for (; (snapshot = ao2_iterator_next(&iter)); ao2_ref(snapshot, -1)) {
1966 if (!strncasecmp(word, snapshot->base->name, wordlen) && (++which > state)) {
1967 if (state != -1) {
1968 ret = ast_strdup(snapshot->base->name);
1969 ao2_ref(snapshot, -1);
1970 break;
1971 }
1972
1973 if (ast_cli_completion_add(ast_strdup(snapshot->base->name))) {
1974 ao2_ref(snapshot, -1);
1975 break;
1976 }
1977 }
1978 }
1979 ao2_iterator_destroy(&iter);
1980 ao2_ref(cached_channels, -1);
1981
1982 return ret;
1983}
#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.
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
enum ast_channel_state state

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 ast_channel_snapshot::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 139 of file main/cli.c.

140{
141 struct module_level *ml;
142 unsigned int res = 0;
143
146 if (!strcasecmp(ml->module, module)) {
147 res = ml->level;
148 break;
149 }
150 }
152
153 return res;
154}
static struct module_level_list debug_modules
Definition main/cli.c:108
map a debug or verbose level to a module name
Definition main/cli.c:99
unsigned int level
Definition main/cli.c:100
struct module_level::@358 entry
char module[0]
Definition main/cli.c:102

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

◆ AST_THREADSTORAGE_CUSTOM_SCOPE()

AST_THREADSTORAGE_CUSTOM_SCOPE ( ast_cli_buf  ,
NULL  ,
ast_free_ptr  ,
static   
)

◆ AST_THREADSTORAGE_RAW()

AST_THREADSTORAGE_RAW ( completion_storage  )

◆ channel_hangup_matches()

static int channel_hangup_matches ( struct ast_cli_args a,
int(*)(const char *, const void *)  matchfn,
const void *  data 
)
static

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

1257{
1258 struct ao2_container *cached_channels;
1259 struct ao2_iterator iter;
1260 struct ast_channel_snapshot *snapshot;
1261 struct ast_channel *c;
1262 int matched = 0;
1263
1264 cached_channels = ast_channel_cache_all();
1265
1266 iter = ao2_iterator_init(cached_channels, 0);
1267 for (; (snapshot = ao2_iterator_next(&iter)); ao2_ref(snapshot, -1)) {
1268 if ((!matchfn || !matchfn(snapshot->base->name, data))
1270 ast_cli(a->fd, "Requested Hangup on channel '%s'\n", snapshot->base->name);
1273 matched++;
1274 }
1275 }
1276 ao2_iterator_destroy(&iter);
1277 ao2_ref(cached_channels, -1);
1278
1279 return matched;
1280}
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition channel.c:1416
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition channel.c:2461
#define ast_channel_unref(c)
Decrease channel reference count.
Definition channel.h:3018
@ AST_SOFTHANGUP_EXPLICIT
Definition channel.h:1168
Main Channel structure associated with a channel.
struct ast_channel_snapshot * snapshot
const char * data
static struct test_val c

References a, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_channel_cache_all(), ast_channel_get_by_name(), ast_channel_unref, ast_cli(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_channel_snapshot::base, c, ast_channel::data, ast_channel_snapshot_base::name, and ast_channel::snapshot.

Referenced by handle_softhangup().

◆ channel_match_by_glob()

static int channel_match_by_glob ( const char *  channel_name,
const void *  pattern 
)
static

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

1239{
1240#if defined(HAVE_FNM_CASEFOLD)
1241 return fnmatch(pattern, channel_name, FNM_NOESCAPE | FNM_PATHNAME | FNM_CASEFOLD);
1242#else
1243 char *lower_channel_name = ast_str_to_lower(ast_strdup(channel_name));
1244 if (lower_channel_name) {
1245 int res = fnmatch(pattern, lower_channel_name, FNM_NOESCAPE | FNM_PATHNAME);
1246 ast_free(lower_channel_name);
1247 return res;
1248 }
1249 return FNM_NOMATCH;
1250#endif
1251}
static force_inline char * ast_str_to_lower(char *str)
Convert a string to all lower-case.
Definition strings.h:1321

References ast_free, ast_str_to_lower(), and ast_strdup.

Referenced by handle_softhangup().

◆ channel_match_by_regex()

static int channel_match_by_regex ( const char *  channel_name,
const void *  data 
)
static

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

1234{
1235 return regexec(data, channel_name, 0, NULL, 0);
1236}

References NULL.

Referenced by handle_softhangup().

◆ channel_set_debug()

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

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

1596{
1597 struct ast_channel *chan = obj;
1598 struct channel_set_debug_args *args = data;
1599
1600 ast_channel_lock(chan);
1601
1602 if (!(ast_channel_fin(chan) & DEBUGCHAN_FLAG) || !(ast_channel_fout(chan) & DEBUGCHAN_FLAG)) {
1603 if (args->is_off) {
1606 } else {
1609 }
1610 ast_cli(args->fd, "Debugging %s on channel %s\n", args->is_off ? "disabled" : "enabled",
1611 ast_channel_name(chan));
1612 }
1613
1614 ast_channel_unlock(chan);
1615
1616 return 0;
1617}
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:2982
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:2983

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

2317{
2319}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408

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

2825{
2826 if (!value) {
2827 return 0;
2828 }
2829
2830 if (!vec || AST_VECTOR_ADD_SORTED(vec, value, strcasecmp)) {
2831 if (vec) {
2832 ast_threadstorage_set_ptr(&completion_storage, NULL);
2833
2835 AST_VECTOR_FREE(vec);
2836 }
2837 ast_free(value);
2838
2839 return -1;
2840 }
2841
2842 return 0;
2843}
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition vector.h:185
#define AST_VECTOR_ADD_SORTED(vec, elem, cmp)
Add an element into a sorted vector.
Definition vector.h:382

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

Referenced by ast_cli_completion_add(), and ast_cli_completion_vector().

◆ cli_has_permissions()

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

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

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

2498{
2499 struct ast_cli_entry *cur = NULL;
2500
2501 while ((cur = cli_next(cur))) {
2502 if (cur == e) {
2503 return 1;
2504 }
2505 }
2506 return 0;
2507}

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

970{
971 if (e) {
972 return AST_LIST_NEXT(e, list);
973 } else {
974 return AST_LIST_FIRST(&helpers);
975 }
976}
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.

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

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

References ast_strdup, ast_strlen_zero(), max, min, module_level::next, 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 2173 of file main/cli.c.

2174{
2175 struct cli_perm *perm;
2176 struct usergroup_cli_perm *user_perm;
2177
2179 while ((user_perm = AST_LIST_REMOVE_HEAD(&cli_perms, list))) {
2180 while ((perm = AST_LIST_REMOVE_HEAD(user_perm->perms, list))) {
2181 ast_free(perm->command);
2182 ast_free(perm);
2183 }
2184 ast_free(user_perm);
2185 }
2187}
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
struct usergroup_cli_perm::@357 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 2479 of file main/cli.c.

2480{
2481 static char cmdline[80];
2482 int x;
2483 /* See how close we get, then print the candidate */
2484 const char *myargv[AST_MAX_CMD_LEN] = { NULL, };
2485
2487 for (x = 0; argv[x]; x++) {
2488 myargv[x] = argv[x];
2489 if (!find_cli(myargv, -1))
2490 break;
2491 }
2493 ast_join(cmdline, sizeof(cmdline), myargv);
2494 return cmdline;
2495}

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

2436{
2437 int matchlen = -1; /* length of longest match so far */
2438 struct ast_cli_entry *cand = NULL, *e=NULL;
2439
2440 while ( (e = cli_next(e)) ) {
2441 /* word-by word regexp comparison */
2442 const char * const *src = cmds;
2443 const char * const *dst = e->cmda;
2444 int n = 0;
2445 for (;; dst++, src += n) {
2446 n = word_match(*src, *dst);
2447 if (n < 0)
2448 break;
2449 }
2450 if (ast_strlen_zero(*dst) || ((*dst)[0] == '[' && ast_strlen_zero(dst[1]))) {
2451 /* no more words in 'e' */
2452 if (ast_strlen_zero(*src)) /* exact match, cannot do better */
2453 break;
2454 /* Here, cmds has more words than the entry 'e' */
2455 if (match_type != 0) /* but we look for almost exact match... */
2456 continue; /* so we skip this one. */
2457 /* otherwise we like it (case 0) */
2458 } else { /* still words in 'e' */
2459 if (ast_strlen_zero(*src))
2460 continue; /* cmds is shorter than 'e', not good */
2461 /* Here we have leftover words in cmds and 'e',
2462 * but there is a mismatch. We only accept this one if match_type == -1
2463 * and this is the last word for both.
2464 */
2465 if (match_type != -1 || !ast_strlen_zero(src[1]) ||
2466 !ast_strlen_zero(dst[1])) /* not the one we look for */
2467 continue;
2468 /* good, we are in case match_type == -1 and mismatch on last word */
2469 }
2470 if (src - cmds > matchlen) { /* remember the candidate */
2471 matchlen = src - cmds;
2472 cand = e;
2473 }
2474 }
2475
2476 return e ? e : cand;
2477}

References ast_strlen_zero(), cli_next(), ast_cli_entry::cmda, 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 354 of file main/cli.c.

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

References AST_LIST_TRAVERSE, module_level::entry, module_level::module, 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 1985 of file main/cli.c.

1986{
1987#define FORMAT_STRING "%-25s %-20s %-20s\n"
1988
1989 struct ast_group_info *gi = NULL;
1990 int numchans = 0;
1991 regex_t regexbuf;
1992 int havepattern = 0;
1993
1994 switch (cmd) {
1995 case CLI_INIT:
1996 e->command = "group show channels";
1997 e->usage =
1998 "Usage: group show channels [pattern]\n"
1999 " Lists all currently active channels with channel group(s) specified.\n"
2000 " Optional regular expression pattern is matched to group names for each\n"
2001 " channel.\n";
2002 return NULL;
2003 case CLI_GENERATE:
2004 return NULL;
2005 }
2006
2007 if (a->argc < 3 || a->argc > 4)
2008 return CLI_SHOWUSAGE;
2009
2010 if (a->argc == 4) {
2011 if (regcomp(&regexbuf, a->argv[3], REG_EXTENDED | REG_NOSUB))
2012 return CLI_SHOWUSAGE;
2013 havepattern = 1;
2014 }
2015
2016 ast_cli(a->fd, FORMAT_STRING, "Channel", "Group", "Category");
2017
2019
2021 while (gi) {
2022 if (!havepattern || !regexec(&regexbuf, gi->group, 0, NULL, 0)) {
2023 ast_cli(a->fd, FORMAT_STRING, ast_channel_name(gi->chan), gi->group, (ast_strlen_zero(gi->category) ? "(default)" : gi->category));
2024 numchans++;
2025 }
2026 gi = AST_LIST_NEXT(gi, group_list);
2027 }
2028
2030
2031 if (havepattern)
2032 regfree(&regexbuf);
2033
2034 ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
2035 return CLI_SUCCESS;
2036#undef FORMAT_STRING
2037}
#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:2975
char * category
Definition channel.h:2977
struct ast_group_info::@223 group_list
struct ast_channel * chan
Definition channel.h:2976

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

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

1460{
1461 struct passwd *pw = NULL;
1462 struct group *gr;
1463 int gid = -1, uid = -1;
1464 char command[AST_MAX_ARGS] = "";
1465 struct ast_cli_entry *ce = NULL;
1466 int found = 0;
1467 char *group, *tmp;
1468
1469 switch (cmd) {
1470 case CLI_INIT:
1471 e->command = "cli check permissions";
1472 e->usage =
1473 "Usage: cli check permissions {<username>|@<groupname>|<username>@<groupname>} [<command>]\n"
1474 " Check permissions config for a user@group or list the allowed commands for the specified user.\n"
1475 " The username or the groupname may be omitted.\n";
1476 return NULL;
1477 case CLI_GENERATE:
1478 if (a->pos >= 4) {
1479 return ast_cli_generator(a->line + strlen("cli check permissions") + strlen(a->argv[3]) + 1, a->word, a->n);
1480 }
1481 return NULL;
1482 }
1483
1484 if (a->argc < 4) {
1485 return CLI_SHOWUSAGE;
1486 }
1487
1488 tmp = ast_strdupa(a->argv[3]);
1489 group = strchr(tmp, '@');
1490 if (group) {
1491 gr = getgrnam(&group[1]);
1492 if (!gr) {
1493 ast_cli(a->fd, "Unknown group '%s'\n", &group[1]);
1494 return CLI_FAILURE;
1495 }
1496 group[0] = '\0';
1497 gid = gr->gr_gid;
1498 }
1499
1500 if (!group && ast_strlen_zero(tmp)) {
1501 ast_cli(a->fd, "You didn't supply a username\n");
1502 } else if (!ast_strlen_zero(tmp) && !(pw = getpwnam(tmp))) {
1503 ast_cli(a->fd, "Unknown user '%s'\n", tmp);
1504 return CLI_FAILURE;
1505 } else if (pw) {
1506 uid = pw->pw_uid;
1507 }
1508
1509 if (a->argc == 4) {
1510 while ((ce = cli_next(ce))) {
1511 /* Hide commands that start with '_' */
1512 if (ce->_full_cmd[0] == '_') {
1513 continue;
1514 }
1515 if (cli_has_permissions(uid, gid, ce->_full_cmd)) {
1516 ast_cli(a->fd, "%30.30s %s\n", ce->_full_cmd, S_OR(ce->summary, "<no description available>"));
1517 found++;
1518 }
1519 }
1520 if (!found) {
1521 ast_cli(a->fd, "You are not allowed to run any command on Asterisk\n");
1522 }
1523 } else {
1524 ast_join(command, sizeof(command), a->argv + 4);
1525 ast_cli(a->fd, "%s '%s%s%s' is %s to run command: '%s'\n", uid >= 0 ? "User" : "Group", tmp,
1526 group && uid >= 0 ? "@" : "",
1527 group ? &group[1] : "",
1528 cli_has_permissions(uid, gid, command) ? "allowed" : "not allowed", command);
1529 }
1530
1531 return CLI_SUCCESS;
1532}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
const char *const summary
Definition cli.h:176

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

◆ handle_cli_malloc_trim()

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

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

2077{
2078 extern int malloc_trim(size_t __pad) __THROW;
2079
2080 switch (cmd) {
2081 case CLI_INIT:
2082 e->command = "malloc trim";
2083 e->usage =
2084 "Usage: malloc trim\n"
2085 " Try to give excess memory back to the OS.\n";
2086 return NULL;
2087 case CLI_GENERATE:
2088 return NULL;
2089 }
2090
2091 if (malloc_trim(0)) {
2092 ast_cli(a->fd, "Returned some memory to the OS.\n");
2093 } else {
2094 ast_cli(a->fd, "No memory returned to the OS.\n");
2095 }
2096
2097 return CLI_SUCCESS;
2098}

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

1441{
1442 switch (cmd) {
1443 case CLI_INIT:
1444 e->command = "cli reload permissions";
1445 e->usage =
1446 "Usage: cli reload permissions\n"
1447 " Reload the 'cli_permissions.conf' file.\n";
1448 return NULL;
1449 case CLI_GENERATE:
1450 return NULL;
1451 }
1452
1454
1455 return CLI_SUCCESS;
1456}
int ast_cli_perms_init(int reload)
Definition main/cli.c:2189

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

1396{
1397 struct usergroup_cli_perm *cp;
1398 struct cli_perm *perm;
1399 struct passwd *pw = NULL;
1400 struct group *gr = NULL;
1401
1402 switch (cmd) {
1403 case CLI_INIT:
1404 e->command = "cli show permissions";
1405 e->usage =
1406 "Usage: cli show permissions\n"
1407 " Shows CLI configured permissions.\n";
1408 return NULL;
1409 case CLI_GENERATE:
1410 return NULL;
1411 }
1412
1414 AST_LIST_TRAVERSE(&cli_perms, cp, list) {
1415 if (cp->uid >= 0) {
1416 pw = getpwuid(cp->uid);
1417 if (pw) {
1418 ast_cli(a->fd, "user: %s [uid=%d]\n", pw->pw_name, cp->uid);
1419 }
1420 } else {
1421 gr = getgrgid(cp->gid);
1422 if (gr) {
1423 ast_cli(a->fd, "group: %s [gid=%d]\n", gr->gr_name, cp->gid);
1424 }
1425 }
1426 ast_cli(a->fd, "Permissions:\n");
1427 if (cp->perms) {
1428 AST_LIST_TRAVERSE(cp->perms, perm, list) {
1429 ast_cli(a->fd, "\t%s -> %s\n", perm->permit ? "permit" : "deny", perm->command);
1430 }
1431 }
1432 ast_cli(a->fd, "\n");
1433 }
1435
1436 return CLI_SUCCESS;
1437}

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

2040{
2041 switch (cmd) {
2042 case CLI_INIT:
2043 e->command = "core waitfullybooted";
2044 e->usage =
2045 "Usage: core waitfullybooted\n"
2046 " Wait until Asterisk has fully booted.\n";
2047 return NULL;
2048 case CLI_GENERATE:
2049 return NULL;
2050 }
2051
2052 while (!ast_fully_booted) {
2053 usleep(100);
2054 }
2055
2056 ast_cli(a->fd, "Asterisk has fully booted.\n");
2057
2058 return CLI_SUCCESS;
2059}
#define ast_fully_booted
Definition options.h:127

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

◆ handle_commandmatchesarray()

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

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

1537{
1538 char *buf, *obuf;
1539 int buflen = 2048;
1540 int len = 0;
1541 char **matches;
1542 int x, matchlen;
1543
1544 switch (cmd) {
1545 case CLI_INIT:
1546 e->command = "_command matchesarray";
1547 e->usage =
1548 "Usage: _command matchesarray \"<line>\" text \n"
1549 " This function is used internally to help with command completion and should.\n"
1550 " never be called by the user directly.\n";
1551 return NULL;
1552 case CLI_GENERATE:
1553 return NULL;
1554 }
1555
1556 if (a->argc != 4)
1557 return CLI_SHOWUSAGE;
1558 if (!(buf = ast_malloc(buflen)))
1559 return CLI_FAILURE;
1560 buf[len] = '\0';
1561 matches = ast_cli_completion_matches(a->argv[2], a->argv[3]);
1562 if (matches) {
1563 for (x=0; matches[x]; x++) {
1564 matchlen = strlen(matches[x]) + 1;
1565 if (len + matchlen >= buflen) {
1566 buflen += matchlen * 3;
1567 obuf = buf;
1568 if (!(buf = ast_realloc(obuf, buflen)))
1569 /* Memory allocation failure... Just free old buffer and be done */
1570 ast_free(obuf);
1571 }
1572 if (buf)
1573 len += sprintf( buf + len, "%s ", matches[x]);
1574 ast_free(matches[x]);
1575 matches[x] = NULL;
1576 }
1577 ast_free(matches);
1578 }
1579
1580 if (buf) {
1581 ast_cli(a->fd, "%s%s",buf, AST_CLI_COMPLETE_EOF);
1582 ast_free(buf);
1583 } else
1584 ast_cli(a->fd, "NULL\n");
1585
1586 return CLI_SUCCESS;
1587}
#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:2789

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

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

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

◆ handle_core_set_debug_channel()

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

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

1620{
1621 struct ast_channel *c = NULL;
1622 static const char * const completions_all[] = { "all", NULL };
1623 static const char * const completions_off[] = { "off", NULL };
1624 struct channel_set_debug_args args = {
1625 .fd = a->fd,
1626 };
1627
1628 switch (cmd) {
1629 case CLI_INIT:
1630 e->command = "core set debug channel";
1631 e->usage =
1632 "Usage: core set debug channel <all|channel> [off]\n"
1633 " Enables/disables debugging on all or on a specific channel.\n";
1634 return NULL;
1635 case CLI_GENERATE:
1636 if (a->pos == 4) {
1637 char *complete = ast_cli_complete(a->word, completions_all, a->n);
1638 if (!complete) {
1639 complete = ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
1640 }
1641 return complete;
1642 } else if (a->pos == 5) {
1643 return ast_cli_complete(a->word, completions_off, a->n);
1644 }
1645
1646 return NULL;
1647 }
1648
1649 if (a->argc == e->args + 2) {
1650 /* 'core set debug channel {all|chan_id}' */
1651 if (!strcasecmp(a->argv[e->args + 1], "off"))
1652 args.is_off = 1;
1653 else
1654 return CLI_SHOWUSAGE;
1655 } else if (a->argc != e->args + 1) {
1656 return CLI_SHOWUSAGE;
1657 }
1658
1659 if (!strcasecmp("all", a->argv[e->args])) {
1660 if (args.is_off) {
1661 global_fin &= ~DEBUGCHAN_FLAG;
1662 global_fout &= ~DEBUGCHAN_FLAG;
1663 } else {
1666 }
1668 } else {
1669 if ((c = ast_channel_get_by_name(a->argv[e->args]))) {
1672 } else {
1673 ast_cli(a->fd, "No such channel %s\n", a->argv[e->args]);
1674 }
1675 }
1676
1677 ast_cli(a->fd, "Debugging on new channels is %s\n", args.is_off ? "disabled" : "enabled");
1678
1679 return CLI_SUCCESS;
1680}
@ 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:1335
unsigned long global_fin
Definition channel.c:98
unsigned long global_fout
Definition channel.h:886
static int channel_set_debug(void *obj, void *arg, void *data, int flags)
Definition main/cli.c:1595
char * ast_cli_complete(const char *word, const char *const choices[], int state)
Definition main/cli.c:1931
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:1950

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

◆ handle_debug()

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

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

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

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

◆ handle_debug_category()

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

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

1683{
1684 const char *argv4 = a->argv ? S_OR(a->argv[4], "") : "";
1685 int offset = strncasecmp(argv4, "off", strlen(argv4)) ? 0 : 1;
1686
1687 switch (cmd) {
1688 case CLI_INIT:
1689 e->command = "core set debug category";
1690 e->usage =
1691 "Usage: core set debug category <category>[:<sublevel>] [category[:<sublevel] ...]\n"
1692 " core set debug category off [<category> [<category>] ...]\n\n"
1693 " Allows enabling and disabling debug logging categories.\n"
1694 " When a category is enabled all relevant debug messages are logged\n"
1695 " for a given category. However, if a sublevel is specified only\n"
1696 " those categorized messages at or below the coded debug sublevel\n"
1697 " are logged.\n";
1698 return NULL;
1699
1700 case CLI_GENERATE:
1701 if (a->pos < e->args) {
1702 return NULL;
1703 }
1704
1705 if (a->pos == 4 && offset) {
1707 }
1708
1709 return ast_debug_category_complete(a->argv + 4,
1710 a->pos - e->args, a->word, a->n - 1);
1711 }
1712
1713 if (a->argc <= e->args) {
1714 return CLI_SHOWUSAGE;
1715 }
1716
1717 ast_debug_category_set_sublevels(a->argv + e->args + offset, a->argc - e->args - offset,
1719
1720 return CLI_SUCCESS;
1721}
#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 452 of file main/cli.c.

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

References a, ast_cli_entry::args, ast_calloc, ast_clear_flag64, ast_cli(), ast_free, AST_OPT_FLAG_DEBUG_MODULE, AST_OPT_FLAG_TRACE_MODULE, ast_options, AST_RWLIST_EMPTY, AST_RWLIST_INSERT_TAIL, AST_RWLIST_REMOVE, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_set_flag64, ast_strdupa, CLI_FAILURE, CLI_SHOWUSAGE, CLI_SUCCESS, DEBUG_HANDLER, debug_modules, find_module_level(), handler(), module_level::level, module_level::module, 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 2671 of file main/cli.c.

2672{
2673 char fullcmd[80];
2674 struct ast_cli_entry *my_e;
2675 char *res = CLI_SUCCESS;
2676
2677 if (cmd == CLI_INIT) {
2678 e->command = "core show help";
2679 e->usage =
2680 "Usage: core show help [topic]\n"
2681 " When called with a topic as an argument, displays usage\n"
2682 " information on the given command. If called without a\n"
2683 " topic, it provides a list of commands.\n";
2684 return NULL;
2685
2686 } else if (cmd == CLI_GENERATE) {
2687 /* skip first 14 or 15 chars, "core show help " */
2688 int l = strlen(a->line);
2689
2690 if (l > 15) {
2691 l = 15;
2692 }
2693 /* XXX watch out, should stop to the non-generator parts */
2694 return __ast_cli_generator(a->line + l, a->word, a->n, 0);
2695 }
2696 if (a->argc == e->args) {
2697 return help1(a->fd, NULL, 0);
2698 }
2699
2701 my_e = find_cli(a->argv + 3, 1); /* try exact match first */
2702 if (!my_e) {
2703 res = help1(a->fd, a->argv + 3, 1 /* locked */);
2705 return res;
2706 }
2707 if (my_e->usage)
2708 ast_cli(a->fd, "%s", my_e->usage);
2709 else {
2710 ast_join(fullcmd, sizeof(fullcmd), a->argv + 3);
2711 ast_cli(a->fd, "No help text available for '%s'.\n", fullcmd);
2712 }
2714 return res;
2715}
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:2641

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

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

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

◆ handle_logger_mute()

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

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

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

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

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

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

◆ handle_refresh()

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

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

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

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

◆ handle_reload()

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

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

272{
273 int x;
274
275 switch (cmd) {
276 case CLI_INIT:
277 e->command = "module reload";
278 e->usage =
279 "Usage: module reload [module ...]\n"
280 " Reloads configuration files for all listed modules which support\n"
281 " reloading, or for all supported modules if none are listed.\n";
282 return NULL;
283
284 case CLI_GENERATE:
285 return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_RELOAD);
286 }
287 if (a->argc == e->args) {
289 return CLI_SUCCESS;
290 }
291 for (x = e->args; x < a->argc; x++) {
292 enum ast_module_reload_result res = ast_module_reload(a->argv[x]);
293 switch (res) {
295 ast_cli(a->fd, "No such module '%s'\n", a->argv[x]);
296 break;
298 ast_cli(a->fd, "The module '%s' does not support reloads\n", a->argv[x]);
299 break;
301 ast_cli(a->fd, "Asterisk cannot reload a module yet; request queued\n");
302 break;
304 ast_cli(a->fd, "The module '%s' reported a reload failure\n", a->argv[x]);
305 break;
307 ast_cli(a->fd, "A module reload request is already in progress; please be patient\n");
308 break;
310 ast_cli(a->fd, "The module '%s' was not properly initialized. Before reloading"
311 " the module, you must run \"module load %s\" and fix whatever is"
312 " preventing the module from being initialized.\n", a->argv[x], a->argv[x]);
313 break;
315 ast_cli(a->fd, "Module '%s' reloaded successfully.\n", a->argv[x]);
316 break;
317 }
318 }
319 return CLI_SUCCESS;
320}
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 1051 of file main/cli.c.

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

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

1724{
1725 struct ast_channel *chan;
1726 struct timeval now;
1727 char cdrtime[256];
1728 struct ast_str *obuf;/*!< Buffer for CDR variables. */
1729 struct ast_str *output;/*!< Accumulation buffer for all output. */
1730 long elapsed_seconds=0;
1731 int hour=0, min=0, sec=0;
1732 struct ast_var_t *var;
1733 struct ast_str *write_transpath = ast_str_alloca(256);
1734 struct ast_str *read_transpath = ast_str_alloca(256);
1735 struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1736 struct ast_bridge *bridge;
1738 char callid_buf[32];
1739 int stream_num;
1740 RAII_VAR(char *, tenant_id, NULL, ast_free);
1741
1742 switch (cmd) {
1743 case CLI_INIT:
1744 e->command = "core show channel";
1745 e->usage =
1746 "Usage: core show channel <channel>\n"
1747 " Shows lots of information about the specified channel.\n";
1748 return NULL;
1749 case CLI_GENERATE:
1750 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
1751 }
1752
1753 if (a->argc != 4) {
1754 return CLI_SHOWUSAGE;
1755 }
1756
1757 obuf = ast_str_thread_get(&ast_str_thread_global_buf, 16);
1758 if (!obuf) {
1759 return CLI_FAILURE;
1760 }
1761
1762 chan = ast_channel_get_by_name(a->argv[3]);
1763 if (!chan) {
1764 ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
1765
1766 return CLI_SUCCESS;
1767 }
1768
1769 output = ast_str_create(8192);
1770 if (!output) {
1771 ast_channel_unref(chan);
1772
1773 return CLI_FAILURE;
1774 }
1775
1776 now = ast_tvnow();
1777 ast_channel_lock(chan);
1778
1780 elapsed_seconds = now.tv_sec - ast_channel_creationtime(chan).tv_sec;
1781 hour = elapsed_seconds / 3600;
1782 min = (elapsed_seconds % 3600) / 60;
1783 sec = elapsed_seconds % 60;
1784 snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
1785 } else {
1786 strcpy(cdrtime, "N/A");
1787 }
1788
1789 ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath);
1790 ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath);
1791
1792 bridge = ast_channel_get_bridge(chan);
1793 callid_buf[0] = '\0';
1794 callid = ast_channel_callid(chan);
1795 if (callid) {
1796 ast_callid_strnprint(callid_buf, sizeof(callid_buf), callid);
1797 }
1798
1800 ast_asprintf(&tenant_id, " TenantID: %s\n", ast_channel_tenantid(chan));
1801 }
1802
1803 ast_str_append(&output, 0,
1804 " -- General --\n"
1805 " Name: %s\n"
1806 " Type: %s\n"
1807 " UniqueID: %s\n"
1808 " LinkedID: %s\n"
1809 "%s"
1810 " Caller ID: %s\n"
1811 " Caller ID Name: %s\n"
1812 "Connected Line ID: %s\n"
1813 "Connected Line ID Name: %s\n"
1814 "Eff. Connected Line ID: %s\n"
1815 "Eff. Connected Line ID Name: %s\n"
1816 " DNID Digits: %s\n"
1817 " Language: %s\n"
1818 " State: %s (%u)\n"
1819 " NativeFormats: %s\n"
1820 " WriteFormat: %s\n"
1821 " ReadFormat: %s\n"
1822 " WriteTranscode: %s %s\n"
1823 " ReadTranscode: %s %s\n"
1824 " Time to Hangup: %ld\n"
1825 " Elapsed Time: %s\n"
1826 " Bridge ID: %s\n"
1827 " -- PBX --\n"
1828 " Context: %s\n"
1829 " Extension: %s\n"
1830 " Priority: %d\n"
1831 " Call Group: %llu\n"
1832 " Pickup Group: %llu\n"
1833 " Application: %s\n"
1834 " Data: %s\n"
1835 " Call Identifier: %s\n",
1836 ast_channel_name(chan),
1837 ast_channel_tech(chan)->type,
1840 !ast_strlen_zero(tenant_id) ? tenant_id : "",
1841 S_COR(ast_channel_caller(chan)->id.number.valid,
1842 ast_channel_caller(chan)->id.number.str, "(N/A)"),
1843 S_COR(ast_channel_caller(chan)->id.name.valid,
1844 ast_channel_caller(chan)->id.name.str, "(N/A)"),
1845 S_COR(ast_channel_connected(chan)->id.number.valid,
1846 ast_channel_connected(chan)->id.number.str, "(N/A)"),
1847 S_COR(ast_channel_connected(chan)->id.name.valid,
1848 ast_channel_connected(chan)->id.name.str, "(N/A)"),
1853 S_OR(ast_channel_dialed(chan)->number.str, "(N/A)"),
1856 ast_channel_state(chan),
1860 ast_str_strlen(write_transpath) ? "Yes" : "No",
1861 ast_str_buffer(write_transpath),
1862 ast_str_strlen(read_transpath) ? "Yes" : "No",
1863 ast_str_buffer(read_transpath),
1864 (long)ast_channel_whentohangup(chan)->tv_sec,
1865 cdrtime,
1866 bridge ? bridge->uniqueid : "(Not bridged)",
1867 ast_channel_context(chan),
1868 ast_channel_exten(chan),
1872 S_OR(ast_channel_appl(chan), "(N/A)"),
1873 S_OR(ast_channel_data(chan), "(Empty)"),
1874 S_OR(callid_buf, "(None)")
1875 );
1876
1877 ast_str_append(&output, 0, " Variables:\n");
1878
1879 AST_LIST_TRAVERSE(ast_channel_varshead(chan), var, entries) {
1880 ast_str_append(&output, 0, "%s=%s\n", ast_var_name(var), ast_var_value(var));
1881 }
1882
1883 if (!(ast_channel_tech(chan)->properties & AST_CHAN_TP_INTERNAL)
1884 && ast_cdr_serialize_variables(ast_channel_name(chan), &obuf, '=', '\n')) {
1885 ast_str_append(&output, 0, " CDR Variables:\n%s\n", ast_str_buffer(obuf));
1886 }
1887
1888 ast_str_append(&output, 0, " -- Streams --\n");
1889 for (stream_num = 0; stream_num < ast_stream_topology_get_count(ast_channel_get_stream_topology(chan)); stream_num++) {
1891 struct ast_variable *metadata = ast_stream_get_metadata_list(stream);
1892
1893 ast_str_append(&output, 0,
1894 "Name: %s\n"
1895 " Type: %s\n"
1896 " State: %s\n"
1897 " Group: %d\n"
1898 " Formats: %s\n"
1899 " Metadata:\n",
1900 ast_stream_get_name(stream),
1903 ast_stream_get_group(stream),
1905 );
1906
1907 if (metadata) {
1908 struct ast_variable *v;
1909 for(v = metadata; v; v = v->next) {
1910 ast_str_append(&output, 0, " %s: %s\n", v->name, v->value);
1911 }
1912 ast_variables_destroy(metadata);
1913 }
1914 }
1915
1916 ast_channel_unlock(chan);
1917
1918 ast_cli(a->fd, "%s", ast_str_buffer(output));
1919 ast_free(output);
1920
1921 ao2_cleanup(bridge);
1922 ast_channel_unref(chan);
1923
1924 return CLI_SUCCESS;
1925}
const char * str
Definition app_jack.c:150
enum queue_result id
Definition app_queue.c:1790
#define var
Definition ast_expr2f.c:605
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition astmm.h:267
#define ao2_cleanup(obj)
Definition astobj2.h:1934
int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep)
Serializes all the data and variables for a current CDR record.
Definition cdr.c:3499
static const char type[]
const char * ast_channel_linkedid(const struct ast_channel *chan)
const char * ast_channel_data(const struct ast_channel *chan)
struct varshead * ast_channel_varshead(struct ast_channel *chan)
const char * ast_channel_tenantid(const struct ast_channel *chan)
struct ast_trans_pvt * ast_channel_readtrans(const struct ast_channel *chan)
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
struct ast_trans_pvt * ast_channel_writetrans(const struct ast_channel *chan)
ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
ast_callid ast_channel_callid(const struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
const char * ast_channel_appl(const struct ast_channel *chan)
struct timeval ast_channel_creationtime(struct ast_channel *chan)
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
Definition channel.c:10582
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)
@ AST_CHAN_TP_INTERNAL
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition channel.h:991
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
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:1260
void ast_callid_strnprint(char *buffer, size_t buffer_size, ast_callid callid)
copy a string representation of the callid into a target string
Definition logger.c:2258
unsigned int ast_callid
const char * ast_stream_get_name(const struct ast_stream *stream)
Get the name of a stream.
Definition stream.c:309
const char * ast_stream_state2str(enum ast_stream_state state)
Convert the state of a stream into a string.
Definition stream.c:388
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition stream.c:791
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition stream.c:768
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition stream.c:373
int ast_stream_get_group(const struct ast_stream *stream)
Get the stream group that a stream is part of.
Definition stream.c:1080
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition stream.c:316
struct ast_variable * ast_stream_get_metadata_list(const struct ast_stream *stream)
Get all stream metadata keys.
Definition stream.c:439
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
Definition stream.c:330
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition strings.h:1139
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition strings.h:87
#define ast_str_alloca(init_len)
Definition strings.h:848
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
Structure that contains information about a bridge.
Definition bridge.h:353
ast_callid callid
Definition bridge.h:365
const ast_string_field uniqueid
Definition bridge.h:405
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition channel.h:648
Number structure.
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:981

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

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

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

1289{
1290 struct ast_channel *c = NULL;
1291 static const char * const completions[] = { "all", NULL };
1292 char *complete = NULL;
1293 int x;
1294
1295 switch (cmd) {
1296 case CLI_INIT:
1297 e->command = "channel request hangup";
1298 e->usage =
1299 "Usage: channel request hangup <all>|<channel> [<channel> ...]\n"
1300 " Request that one or more channels be hung up. The hangup takes\n"
1301 " effect the next time the driver reads or writes from the channel.\n\n"
1302 " If 'all' is specified instead of a channel name, all channels\n"
1303 " will see the hangup request.\n\n"
1304 " A POSIX Extended Regular Expression can be provided in the place\n"
1305 " of a fixed channel name by wrapping it in forward slashes\n"
1306 " (e.g. /^PJSIP.*/). Note that the expression will match any part\n"
1307 " of the channel name unless anchored explicitly by ^ and/or $.\n\n"
1308 " Finally, wildcards (*) and other glob-like characters can also\n"
1309 " be used to match more than one channel. Similar to how path globs\n"
1310 " behave, a forward slash cannot be matched with a wildcard or\n"
1311 " bracket expression. In other words, if you want to hangup all\n"
1312 " Local channels, you must specify Local/* and not Loc*.\n";
1313 return NULL;
1314 case CLI_GENERATE:
1315 if (a->pos < e->args) {
1316 return NULL;
1317 } else if (a->pos == e->args) {
1318 complete = ast_cli_complete(a->word, completions, a->n);
1319 }
1320 if (!complete) {
1321 complete = ast_complete_channels(a->line, a->word, a->pos, a->n - 1, a->pos);
1322 }
1323 return complete;
1324 }
1325
1326 if (a->argc < 4) {
1327 return CLI_SHOWUSAGE;
1328 }
1329
1330 if (!strcasecmp(a->argv[3], "all")) {
1332 return CLI_SUCCESS;
1333 }
1334
1335 for (x = e->args; x < a->argc; x++) {
1336 /* Try to find a literal channel name first */
1337 if ((c = ast_channel_get_by_name(a->argv[x]))) {
1339 ast_cli(a->fd, "Requested Hangup on channel '%s'\n", ast_channel_name(c));
1343 continue;
1344 }
1345
1346 if (arg_looks_like_regex(a->argv[x])) {
1347 char *pattern = ast_strdup(a->argv[x]);
1348 regex_t re;
1349 int res;
1350
1351 if (!pattern) {
1352 return CLI_FAILURE;
1353 }
1354
1355 pattern[strlen(pattern) - 1] = 0;
1356 res = regcomp(&re, &pattern[1], REG_EXTENDED | REG_ICASE | REG_NOSUB);
1357 ast_free(pattern);
1358 if (res) {
1359 char errbuf[MAX_REGEX_ERROR_LEN];
1360 regerror(res, &re, errbuf, sizeof(errbuf));
1361 ast_cli(a->fd, "%s is not a valid POSIX Extended Regular Expression: %s\n",
1362 a->argv[x], errbuf);
1363 continue;
1364 }
1365
1367 ast_cli(a->fd, "%s did not match a known channel\n", a->argv[x]);
1368 }
1369 regfree(&re);
1370 } else if (arg_looks_like_glob(a->argv[x])) {
1371#if defined(HAVE_FNM_CASEFOLD)
1373 ast_cli(a->fd, "%s did not match a known channel\n", a->argv[x]);
1374 }
1375#else
1376 char *pattern = ast_str_to_lower(ast_strdup(a->argv[x]));
1377 if (pattern) {
1379 ast_cli(a->fd, "%s did not match a known channel\n", a->argv[x]);
1380 }
1381 ast_free(pattern);
1382 } else {
1383 return CLI_FAILURE;
1384 }
1385#endif
1386 } else {
1387 ast_cli(a->fd, "%s is not a known channel\n", a->argv[x]);
1388 }
1389 }
1390
1391 return CLI_SUCCESS;
1392}
#define arg_looks_like_glob(n)
Definition main/cli.c:1285
#define arg_looks_like_regex(n)
Definition main/cli.c:1282
#define MAX_REGEX_ERROR_LEN
Definition main/cli.c:119
static int channel_match_by_regex(const char *channel_name, const void *data)
Definition main/cli.c:1233
static int channel_hangup_matches(struct ast_cli_args *a, int(*matchfn)(const char *, const void *), const void *data)
Definition main/cli.c:1253
static int channel_match_by_glob(const char *channel_name, const void *pattern)
Definition main/cli.c:1238

References a, arg_looks_like_glob, arg_looks_like_regex, ast_cli_entry::args, ast_channel_get_by_name(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_cli(), ast_cli_complete(), ast_complete_channels(), ast_free, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_str_to_lower(), ast_strdup, c, channel_hangup_matches(), channel_match_by_glob(), channel_match_by_regex(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, MAX_REGEX_ERROR_LEN, NULL, ast_cli_entry::usage, and ast_channel::x.

◆ handle_trace()

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

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

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

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

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

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

◆ handle_verbose()

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

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

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

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

2642{
2643 char matchstr[80] = "";
2644 struct ast_cli_entry *e = NULL;
2645 int len = 0;
2646 int found = 0;
2647
2648 if (match) {
2649 ast_join(matchstr, sizeof(matchstr), match);
2650 len = strlen(matchstr);
2651 }
2652 if (!locked)
2654 while ( (e = cli_next(e)) ) {
2655 /* Hide commands that start with '_' */
2656 if (e->_full_cmd[0] == '_')
2657 continue;
2658 if (match && strncasecmp(matchstr, e->_full_cmd, len))
2659 continue;
2660 ast_cli(fd, "%-30s -- %s\n", e->_full_cmd,
2661 S_OR(e->summary, "<no description available>"));
2662 found++;
2663 }
2664 if (!locked)
2666 if (!found && matchstr[0])
2667 ast_cli(fd, "No such command '%s'.\n", matchstr);
2668 return CLI_SUCCESS;
2669}
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition chan_iax2.c:2388

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

Referenced by handle_help().

◆ is_prefix()

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

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

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

2387{
2388 int lw;
2389 char *s, *t1;
2390
2391 *actual = 0;
2392 if (ast_strlen_zero(token))
2393 return NULL;
2394 if (ast_strlen_zero(word))
2395 word = ""; /* dummy */
2396 lw = strlen(word);
2397 if (strcspn(word, cli_rsvd) != lw)
2398 return NULL; /* no match if word has reserved chars */
2399 if (strchr(cli_rsvd, token[0]) == NULL) { /* regular match */
2400 if (strncasecmp(token, word, lw)) /* no match */
2401 return NULL;
2402 *actual = 1;
2403 return (pos != 0) ? NULL : ast_strdup(token);
2404 }
2405 /* now handle regexp match */
2406
2407 /* Wildcard always matches, so we never do is_prefix on them */
2408
2409 t1 = ast_strdupa(token + 1); /* copy, skipping first char */
2410 while (pos >= 0 && (s = strsep(&t1, cli_rsvd)) && *s) {
2411 if (*s == '%') /* wildcard */
2412 continue;
2413 if (strncasecmp(s, word, lw)) /* no match */
2414 continue;
2415 (*actual)++;
2416 if (pos-- == 0)
2417 return ast_strdup(s);
2418 }
2419 return NULL;
2420}
char * strsep(char **str, const char *delims)
static const char cli_rsvd[]
Definition main/cli.c:2148

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

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

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

Referenced by handle_modlist().

◆ more_words()

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

returns true if there are more words to match

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

2936{
2937 int i;
2938 for (i = 0; dst[i]; i++) {
2939 if (dst[i][0] != '[')
2940 return -1;
2941 }
2942 return 0;
2943}

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

2718{
2719 char *duplicate, *cur;
2720 int x = 0;
2721 int quoted = 0;
2722 int escaped = 0;
2723 int whitespace = 1;
2724 int dummy = 0;
2725
2726 if (trailingwhitespace == NULL)
2727 trailingwhitespace = &dummy;
2728 *trailingwhitespace = 0;
2729 if (s == NULL) /* invalid, though! */
2730 return NULL;
2731 /* make a copy to store the parsed string */
2732 if (!(duplicate = ast_strdup(s)))
2733 return NULL;
2734
2735 cur = duplicate;
2736
2737 /* Remove leading spaces from the command */
2738 while (isspace(*s)) {
2739 cur++;
2740 s++;
2741 }
2742
2743 /* scan the original string copying into cur when needed */
2744 for (; *s ; s++) {
2745 if (x >= max - 1) {
2746 ast_log(LOG_WARNING, "Too many arguments, truncating at %s\n", s);
2747 break;
2748 }
2749 if (*s == '"' && !escaped) {
2750 quoted = !quoted;
2751 if (quoted && whitespace) {
2752 /* start a quoted string from previous whitespace: new argument */
2753 argv[x++] = cur;
2754 whitespace = 0;
2755 }
2756 } else if ((*s == ' ' || *s == '\t') && !(quoted || escaped)) {
2757 /* If we are not already in whitespace, and not in a quoted string or
2758 processing an escape sequence, and just entered whitespace, then
2759 finalize the previous argument and remember that we are in whitespace
2760 */
2761 if (!whitespace) {
2762 *cur++ = '\0';
2763 whitespace = 1;
2764 }
2765 } else if (*s == '\\' && !escaped) {
2766 escaped = 1;
2767 } else {
2768 if (whitespace) {
2769 /* we leave whitespace, and are not quoted. So it's a new argument */
2770 argv[x++] = cur;
2771 whitespace = 0;
2772 }
2773 *cur++ = *s;
2774 escaped = 0;
2775 }
2776 }
2777 /* Null terminate */
2778 *cur++ = '\0';
2779 /* XXX put a NULL in the last argument, because some functions that take
2780 * the array may want a null-terminated array.
2781 * argc still reflects the number of non-NULL entries.
2782 */
2783 argv[x] = NULL;
2784 *argc = x;
2785 *trailingwhitespace = whitespace;
2786 return duplicate;
2787}
static void dummy(char *unused,...)

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

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

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

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

Referenced by ast_cli_unregister().

◆ set_full_cmd()

static int set_full_cmd ( struct ast_cli_entry e)
static

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

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

2155{
2156 int i;
2157 char buf[80];
2158
2159 ast_join(buf, sizeof(buf), e->cmda);
2160 e->_full_cmd = ast_strdup(buf);
2161 if (!e->_full_cmd) {
2162 ast_log(LOG_WARNING, "-- cannot allocate <%s>\n", buf);
2163 return -1;
2164 }
2165 e->cmdlen = strcspn(e->_full_cmd, cli_rsvd);
2166 for (i = 0; e->cmda[i]; i++)
2167 ;
2168 e->args = i;
2169 return 0;
2170}

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

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

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

2347{
2348 int l;
2349 char *pos;
2350
2351 if (ast_strlen_zero(cmd) || ast_strlen_zero(cli_word))
2352 return -1;
2353 if (!strchr(cli_rsvd, cli_word[0])) /* normal match */
2354 return (strcasecmp(cmd, cli_word) == 0) ? 1 : -1;
2355 l = strlen(cmd);
2356 /* wildcard match - will extend in the future */
2357 if (l > 0 && cli_word[0] == '%') {
2358 return 1; /* wildcard */
2359 }
2360
2361 /* Start a search for the command entered against the cli word in question */
2362 pos = strcasestr(cli_word, cmd);
2363 while (pos) {
2364
2365 /*
2366 *Check if the word matched with is surrounded by reserved characters on both sides
2367 * and isn't at the beginning of the cli_word since that would make it check in a location we shouldn't know about.
2368 * If it is surrounded by reserved chars and isn't at the beginning, it's a match.
2369 */
2370 if (pos != cli_word && strchr(cli_rsvd, pos[-1]) && strchr(cli_rsvd, pos[l])) {
2371 return 1; /* valid match */
2372 }
2373
2374 /* Ok, that one didn't match, strcasestr to the next appearance of the command and start over.*/
2375 pos = strcasestr(pos + 1, cmd);
2376 }
2377 /* If no matches were found over the course of the while loop, we hit the end of the string. It's a mismatch. */
2378 return -1;
2379}

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

Referenced by __ast_cli_generator(), and find_cli().

Variable Documentation

◆ cli_channels_cli

struct ast_cli_entry cli_channels_cli[]
static

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

2136 {
2137 AST_CLI_DEFINE(handle_chanlist, "Display information on channels"),
2138 AST_CLI_DEFINE(handle_showcalls, "Display information on calls"),
2139 AST_CLI_DEFINE(handle_showchan, "Display information on a specific channel"),
2140 AST_CLI_DEFINE(handle_core_set_debug_channel, "Enable/disable debugging on a channel"),
2141 AST_CLI_DEFINE(group_show_channels, "Display active channels with group(s)"),
2142 AST_CLI_DEFINE(handle_softhangup, "Request a hangup on a given channel"),
2143};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197
static char * handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:1723
static char * handle_chanlist(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:1107
static char * group_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:1985
static char * handle_showcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:1051
static char * handle_softhangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:1288
static char * handle_core_set_debug_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:1619

Referenced by ast_cli_channels_init(), and cli_channels_shutdown().

◆ cli_cli

struct ast_cli_entry cli_cli[]
static

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

2104 {
2105 AST_CLI_DEFINE(handle_commandmatchesarray, "Returns command matches array"),
2106
2107 AST_CLI_DEFINE(handle_debug_category, "Enable/disable debugging categories"),
2108
2109 AST_CLI_DEFINE(handle_debug, "Set level of debug chattiness"),
2110 AST_CLI_DEFINE(handle_trace, "Set level of trace chattiness"),
2111 AST_CLI_DEFINE(handle_verbose, "Set level of verbose chattiness"),
2112
2113 AST_CLI_DEFINE(handle_help, "Display help list, or specific help on a command"),
2114 AST_CLI_DEFINE(handle_logger_mute, "Toggle logging output to a console"),
2115
2116 AST_CLI_DEFINE(handle_modlist, "List modules and info"),
2117 AST_CLI_DEFINE(handle_load, "Load a module by name"),
2118 AST_CLI_DEFINE(handle_reload, "Reload configuration for a module"),
2119 AST_CLI_DEFINE(handle_core_reload, "Global reload"),
2120 AST_CLI_DEFINE(handle_unload, "Unload a module by name"),
2121 AST_CLI_DEFINE(handle_refresh, "Completely unloads and loads a module by name"),
2122
2123 AST_CLI_DEFINE(handle_showuptime, "Show uptime information"),
2124
2125 AST_CLI_DEFINE(handle_cli_reload_permissions, "Reload CLI permissions config"),
2126 AST_CLI_DEFINE(handle_cli_show_permissions, "Show CLI permissions"),
2127 AST_CLI_DEFINE(handle_cli_check_permissions, "Try a permissions config for a user"),
2128 AST_CLI_DEFINE(handle_cli_wait_fullybooted, "Wait for Asterisk to be fully booted"),
2129
2130#ifdef HAVE_MALLOC_TRIM
2131 AST_CLI_DEFINE(handle_cli_malloc_trim, "Return excess memory to the OS"),
2132#endif
2133
2134};
static char * handle_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:271
static char * handle_cli_reload_permissions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
handles CLI command 'cli reload permissions'
Definition main/cli.c:1440
static char * handle_trace(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:633
static char * handle_cli_show_permissions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
handles CLI command 'cli show permissions'
Definition main/cli.c:1395
static char * handle_logger_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:786
static char * handle_commandmatchesarray(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:1536
static char * handle_load(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:243
static char * handle_modlist(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:1011
static char * handle_refresh(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:811
static char * handle_unload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:848
static char * handle_cli_check_permissions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
handles CLI command 'cli check permissions'
Definition main/cli.c:1459
static char * handle_help(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:2671
static char * handle_cli_malloc_trim(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:2076
static char * handle_cli_wait_fullybooted(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:2039
static char * handle_core_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:322
static char * handle_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:575
static char * handle_showuptime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:978
static char * handle_debug_category(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:1682
static char * handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition main/cli.c:686

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

Referenced by ast_cli_perms_init(), and cli_has_permissions().

◆ cli_perms

◆ cli_rsvd

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

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

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

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

◆ climodentryfd

int climodentryfd = -1
static

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

Referenced by handle_modlist(), and modlist_modentry().

◆ climodentrylock

ast_mutex_t climodentrylock = AST_MUTEX_INIT_VALUE
static

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

Referenced by handle_modlist().

◆ current

size_t current

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

◆ debug_modules

struct module_level_list debug_modules = AST_RWLIST_HEAD_INIT_VALUE
static

lists of module names and their debug/trace levels

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

◆ helpers

◆ max

size_t max

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

Referenced by ast_cli_perms_init().

◆ permsconfiglock

ast_mutex_t permsconfiglock = AST_MUTEX_INIT_VALUE
static

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

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

Referenced by ast_cli_perms_init().

◆ [struct]

struct { ... } shutdown_commands

◆ shutdown_commands_lock

ast_rwlock_t shutdown_commands_lock = AST_RWLOCK_INIT_VALUE
static

◆ trace_modules

struct module_level_list trace_modules = AST_RWLIST_HEAD_INIT_VALUE
static

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

Referenced by ast_trace_get_by_module(), and handle_debug_or_trace().