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

Standard Command Line Interface. More...

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

Go to the source code of this file.

Data Structures

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

Macros

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

Functions

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

Variables

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

Detailed Description

Standard Command Line Interface.

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

Definition in file main/cli.c.

Macro Definition Documentation

◆ AST_CLI_INITLEN

#define AST_CLI_INITLEN   256

Initial buffer size for resulting strings in ast_cli()

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

◆ CONCISE_FORMAT_STRING

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

◆ DAY

#define DAY   (HOUR*24)

◆ DEBUG_HANDLER

#define DEBUG_HANDLER   0

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

◆ FORMAT_STRING [1/2]

#define FORMAT_STRING   "%-20.20s %-20.20s %-7.7s %-30.30s\n"

◆ FORMAT_STRING [2/2]

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

◆ FORMAT_STRING2

#define FORMAT_STRING2   "%-20.20s %-20.20s %-7.7s %-30.30s\n"

◆ HOUR

#define HOUR   (MINUTE*60)

◆ MINUTE

#define MINUTE   (SECOND*60)

◆ MODLIST_FORMAT

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

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

◆ MODLIST_FORMAT2

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

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

◆ NEEDCOMMA

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

◆ SECOND

#define SECOND   (1)

◆ TRACE_HANDLER

#define TRACE_HANDLER   1

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

◆ VERBOSE_FORMAT_STRING

#define VERBOSE_FORMAT_STRING   "%-20.20s %-20.20s %-16.16s %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   "%-20.20s %-20.20s %-16.16s %-4.4s %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-11.11s %-20.20s\n"

◆ VERBOSE_HANDLER

#define VERBOSE_HANDLER   2

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

◆ WEEK

#define WEEK   (DAY*7)

◆ YEAR

#define YEAR   (DAY*365)

Function Documentation

◆ __ast_cli_generator()

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

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

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

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

Referenced by ast_cli_generator(), and handle_help().

◆ __ast_cli_register()

int __ast_cli_register ( struct ast_cli_entry e,
struct ast_module module 
)

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

2455 {
2456  struct ast_cli_entry *cur;
2457  int i, lf, ret = -1;
2458 
2459  struct ast_cli_args a; /* fake argument */
2460  char **dst = (char **)e->cmda; /* need to cast as the entry is readonly */
2461  char *s;
2462 
2464 
2465  if (cli_is_registered(e)) {
2466  ast_log(LOG_WARNING, "Command '%s' already registered (the same ast_cli_entry)\n",
2467  S_OR(e->_full_cmd, e->command));
2468  ret = 0; /* report success */
2469  goto done;
2470  }
2471 
2472  memset(&a, '\0', sizeof(a));
2473 
2474  e->module = module;
2475  /* No module reference needed here, the module called us. */
2476  e->handler(e, CLI_INIT, &a);
2477 
2478  /* XXX check that usage and command are filled up */
2479  s = ast_skip_blanks(e->command);
2480  s = e->command = ast_strdup(s);
2481  for (i=0; !ast_strlen_zero(s) && i < AST_MAX_CMD_LEN-1; i++) {
2482  *dst++ = s; /* store string */
2483  s = ast_skip_nonblanks(s);
2484  if (*s == '\0') /* we are done */
2485  break;
2486  *s++ = '\0';
2487  s = ast_skip_blanks(s);
2488  }
2489  *dst++ = NULL;
2490 
2491  if (find_cli(e->cmda, 1)) {
2492  ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n",
2493  S_OR(e->_full_cmd, e->command));
2494  goto done;
2495  }
2496  if (set_full_cmd(e)) {
2497  ast_log(LOG_WARNING, "Error registering CLI Command '%s'\n",
2498  S_OR(e->_full_cmd, e->command));
2499  goto done;
2500  }
2501 
2502  lf = e->cmdlen;
2504  int len = cur->cmdlen;
2505  if (lf < len)
2506  len = lf;
2507  if (strncasecmp(e->_full_cmd, cur->_full_cmd, len) < 0) {
2509  break;
2510  }
2511  }
2513 
2514  if (!cur)
2515  AST_RWLIST_INSERT_TAIL(&helpers, e, list);
2516  ret = 0; /* success */
2517 
2518 done:
2520  if (ret) {
2521  ast_free(e->command);
2522  e->command = NULL;
2523  }
2524 
2525  return ret;
2526 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_log
Definition: astobj2.c:42
@ CLI_INIT
Definition: cli.h:152
#define AST_MAX_CMD_LEN
Definition: cli.h:48
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define LOG_WARNING
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:610
static int set_full_cmd(struct ast_cli_entry *e)
Definition: main/cli.c:2080
static int cli_is_registered(struct ast_cli_entry *e)
Definition: main/cli.c:2412
static struct ast_cli_entry * find_cli(const char *const cmds[], int match_type)
Definition: main/cli.c:2350
char * ast_skip_nonblanks(const char *str)
Gets a pointer to first whitespace character in a string.
Definition: strings.h:204
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
int cmdlen
Definition: cli.h:182
char * _full_cmd
Definition: cli.h:181
int done
Definition: test_amihooks.c:48

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

Referenced by __ast_cli_register_multiple().

◆ __ast_cli_register_multiple()

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

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

2532 {
2533  int i, res = 0;
2534 
2535  for (i = 0; i < len; i++) {
2536  res |= __ast_cli_register(e + i, module);
2537  }
2538 
2539  return res;
2540 }
int __ast_cli_register(struct ast_cli_entry *e, struct ast_module *module)
Definition: main/cli.c:2454

References __ast_cli_register(), and len().

◆ __init_ast_cli_buf()

static void __init_ast_cli_buf ( void  )
static

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

119 {

◆ allowed_on_shutdown()

static int allowed_on_shutdown ( struct ast_cli_entry e)
static

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

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

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

Referenced by ast_cli_command_full().

◆ ast_builtins_init()

void ast_builtins_init ( void  )

initialize the _full_cmd string in * each of the builtins.

Provided by cli.c

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

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

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

Referenced by asterisk_daemon().

◆ ast_cli()

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

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

119 {
120  int res;
121  struct ast_str *buf;
122  va_list ap;
123 
125  return;
126 
127  va_start(ap, fmt);
128  res = ast_str_set_va(&buf, 0, fmt, ap);
129  va_end(ap);
130 
131  if (res != AST_DYNSTR_BUILD_FAILED) {
133  }
134 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct ast_threadstorage ast_cli_buf
Definition: main/cli.c:110
#define AST_CLI_INITLEN
Initial buffer size for resulting strings in ast_cli()
Definition: main/cli.c:116
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:739
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:1008
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:711
@ AST_DYNSTR_BUILD_FAILED
Definition: strings.h:921
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:887
Support for dynamic strings.
Definition: strings.h:604
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: main/utils.c:1738

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

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

◆ ast_cli_allow_at_shutdown()

int ast_cli_allow_at_shutdown ( struct ast_cli_entry e)

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

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

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

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

3061 {
3062  int res;
3063 
3067 
3068  return res;
3069 }
#define ast_rwlock_wrlock(a)
Definition: lock.h:234
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256

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

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

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

2974 {
2975  const char *args[AST_MAX_ARGS + 1];
2976  struct ast_cli_entry *e = NULL;
2977  int x;
2978  char *duplicate = parse_args(s, &x, args + 1, AST_MAX_ARGS, NULL);
2979  char tmp[AST_MAX_ARGS + 1];
2980  char *retval = CLI_FAILURE;
2981  struct ast_cli_args a = {
2982  .fd = fd, .argc = x, .argv = args+1 };
2983 
2984  if (duplicate == NULL)
2985  return RESULT_FAILURE;
2986 
2987  if (x < 1) /* We need at least one entry, otherwise ignore */
2988  goto done;
2989 
2991  e = find_cli(args + 1, 0);
2992  if (e)
2995  if (e == NULL) {
2996  ast_cli(fd, "No such command '%s' (type 'core show help %s' for other possible commands)\n", s, find_best(args + 1));
2997  goto done;
2998  }
2999 
3000  if (ast_shutting_down() && !allowed_on_shutdown(e)) {
3001  ast_cli(fd, "Command '%s' cannot be run during shutdown\n", s);
3002  goto done;
3003  }
3004 
3005  ast_join(tmp, sizeof(tmp), args + 1);
3006  /* Check if the user has rights to run this command. */
3007  if (!cli_has_permissions(uid, gid, tmp)) {
3008  ast_cli(fd, "You don't have permissions to run '%s' command\n", tmp);
3009  goto done;
3010  }
3011 
3012  /*
3013  * Within the handler, argv[-1] contains a pointer to the ast_cli_entry.
3014  * Remember that the array returned by parse_args is NULL-terminated.
3015  */
3016  args[0] = (char *)e;
3017 
3018  /* If the command is in a module it must be running. */
3019  if (!e->module || ast_module_running_ref(e->module)) {
3020  retval = e->handler(e, CLI_HANDLER, &a);
3022  }
3023 
3024  if (retval == CLI_SHOWUSAGE) {
3025  ast_cli(fd, "%s", S_OR(e->usage, "Invalid usage, but no usage information available.\n"));
3026  } else if (retval == CLI_FAILURE) {
3027  ast_cli(fd, "Command '%s' failed.\n", s);
3028  }
3029 
3030 done:
3031  if (e) {
3032  ast_atomic_fetchadd_int(&e->inuse, -1);
3033  }
3034  ast_free(duplicate);
3036 }
int ast_shutting_down(void)
Definition: asterisk.c:1870
static int tmp()
Definition: bt_open.c:389
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
#define RESULT_SUCCESS
Definition: cli.h:40
@ CLI_HANDLER
Definition: cli.h:154
#define CLI_FAILURE
Definition: cli.h:46
#define RESULT_FAILURE
Definition: cli.h:42
static ENTRY retval
Definition: hsearch.c:50
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
void ast_cli(int fd, const char *fmt,...)
Definition: main/cli.c:118
static int allowed_on_shutdown(struct ast_cli_entry *e)
Definition: main/cli.c:2956
static int cli_has_permissions(int uid, int gid, const char *command)
Definition: main/cli.c:183
static char * find_best(const char *argv[])
Definition: main/cli.c:2394
const int fd
Definition: cli.h:159
int inuse
Definition: cli.h:179
const char * usage
Definition: cli.h:177
const char * args

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

Referenced by ast_cli_command_multiple_full().

◆ ast_cli_command_multiple_full()

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

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

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

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

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

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

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

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

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

Referenced by cli_odbc_read(), complete_skinny_reset(), complete_skinny_show_line(), handle_bridge_kick_channel(), handle_cli_iax2_prune_realtime(), handle_core_set_debug_channel(), handle_orig(), handle_showcalls(), handle_softhangup(), sip_prune_realtime(), sip_qualify_peer(), sip_show_peer(), sip_show_user(), 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 2760 of file main/cli.c.

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

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

Referenced by aeap_tab_complete_name(), ast_cli_complete(), ast_complete_applications(), ast_complete_channels(), category_complete(), cli_complete_endpoint(), cli_complete_show(), cli_complete_uri(), complete_bridge_live_search(), complete_bridge_participant(), complete_bridge_technology(), complete_channeltypes(), complete_config_module(), complete_config_option(), complete_config_type(), complete_core_id(), complete_country(), complete_indications(), complete_show_sorcery_object(), complete_trans_path_choice(), handle_cli_config_reload(), handle_debug_category(), handle_showmanager(), handle_showmancmd(), module_load_helper_on_file(), stir_shaken_tab_complete_name(), 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 2704 of file main/cli.c.

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

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

Referenced by handle_commandmatchesarray().

◆ ast_cli_completion_vector()

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

Generates a vector of strings for CLI completion.

Parameters
textComplete input being matched.
wordCurrent word being matched

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

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

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

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

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

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

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

◆ ast_cli_generator()

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

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

Return values
0on success
-1on failure

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

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

2952 {
2953  return __ast_cli_generator(text, word, state, 1);
2954 }
static char * __ast_cli_generator(const char *text, const char *word, int state, int lock)
Definition: main/cli.c:2863

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

2116 {
2117  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2118  struct ast_config *cfg;
2119  char *cat = NULL;
2120  struct ast_variable *v;
2121  struct usergroup_cli_perm *user_group, *cp_entry;
2122  struct cli_perm *perm = NULL;
2123  struct passwd *pw;
2124  struct group *gr;
2125 
2127  ast_log(LOG_NOTICE, "You must wait until last 'cli reload permissions' command finish\n");
2128  return 1;
2129  }
2130 
2131  cfg = ast_config_load2(perms_config, "" /* core, can't reload */, config_flags);
2132  if (!cfg) {
2134  return 1;
2135  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2137  return 0;
2138  }
2139 
2140  /* free current structures. */
2142 
2143  while ((cat = ast_category_browse(cfg, cat))) {
2144  if (!strcasecmp(cat, "general")) {
2145  /* General options */
2146  for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
2147  if (!strcasecmp(v->name, "default_perm")) {
2148  cli_default_perm = (!strcasecmp(v->value, "permit")) ? 1: 0;
2149  }
2150  }
2151  continue;
2152  }
2153 
2154  /* users or groups */
2155  gr = NULL, pw = NULL;
2156  if (cat[0] == '@') {
2157  /* This is a group */
2158  gr = getgrnam(&cat[1]);
2159  if (!gr) {
2160  ast_log (LOG_WARNING, "Unknown group '%s'\n", &cat[1]);
2161  continue;
2162  }
2163  } else {
2164  /* This is a user */
2165  pw = getpwnam(cat);
2166  if (!pw) {
2167  ast_log (LOG_WARNING, "Unknown user '%s'\n", cat);
2168  continue;
2169  }
2170  }
2171  user_group = NULL;
2172  /* Check for duplicates */
2174  AST_LIST_TRAVERSE(&cli_perms, cp_entry, list) {
2175  if ((pw && cp_entry->uid == pw->pw_uid) || (gr && cp_entry->gid == gr->gr_gid)) {
2176  /* if it is duplicated, just added this new settings, to
2177  the current list. */
2178  user_group = cp_entry;
2179  break;
2180  }
2181  }
2183 
2184  if (!user_group) {
2185  /* alloc space for the new user config. */
2186  user_group = ast_calloc(1, sizeof(*user_group));
2187  if (!user_group) {
2188  continue;
2189  }
2190  user_group->uid = (pw ? pw->pw_uid : -1);
2191  user_group->gid = (gr ? gr->gr_gid : -1);
2192  user_group->perms = ast_calloc(1, sizeof(*user_group->perms));
2193  if (!user_group->perms) {
2194  ast_free(user_group);
2195  continue;
2196  }
2197  }
2198  for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
2199  if (ast_strlen_zero(v->value)) {
2200  /* we need to check this condition cause it could break security. */
2201  ast_log(LOG_WARNING, "Empty permit/deny option in user '%s'\n", cat);
2202  continue;
2203  }
2204  if (!strcasecmp(v->name, "permit")) {
2205  perm = ast_calloc(1, sizeof(*perm));
2206  if (perm) {
2207  perm->permit = 1;
2208  perm->command = ast_strdup(v->value);
2209  }
2210  } else if (!strcasecmp(v->name, "deny")) {
2211  perm = ast_calloc(1, sizeof(*perm));
2212  if (perm) {
2213  perm->permit = 0;
2214  perm->command = ast_strdup(v->value);
2215  }
2216  } else {
2217  /* up to now, only 'permit' and 'deny' are possible values. */
2218  ast_log(LOG_WARNING, "Unknown '%s' option\n", v->name);
2219  continue;
2220  }
2221  if (perm) {
2222  /* Added the permission to the user's list. */
2223  AST_LIST_INSERT_TAIL(user_group->perms, perm, list);
2224  perm = NULL;
2225  }
2226  }
2228  AST_RWLIST_INSERT_TAIL(&cli_perms, user_group, list);
2230  }
2231 
2232  ast_config_destroy(cfg);
2234  return 0;
2235 }
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3327
@ CONFIG_FLAG_FILEUNCHANGED
#define CONFIG_STATUS_FILEUNCHANGED
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3220
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
#define LOG_NOTICE
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_mutex_trylock(a)
Definition: lock.h:189
static ast_mutex_t permsconfiglock
mutex used to prevent a user from running the 'cli reload permissions' command while it is already ru...
Definition: main/cli.c:91
static int cli_default_perm
Default permissions value 1=Permit 0=Deny.
Definition: main/cli.c:87
static void destroy_user_perms(void)
cleanup (free) cli_perms linkedlist.
Definition: main/cli.c:2099
static const char perms_config[]
CLI permissions config file.
Definition: main/cli.c:85
static int reload(void)
Structure used to handle boolean flags.
Definition: utils.h:199
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
List of restrictions per user.
Definition: main/cli.c:69
unsigned int permit
Definition: main/cli.c:70
char * command
Definition: main/cli.c:71
List of users and permissions.
Definition: main/cli.c:93
list of users to apply restrictions.
Definition: main/cli.c:78
struct cli_perm_head * perms
Definition: main/cli.c:81

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

Referenced by asterisk_daemon(), and handle_cli_reload_permissions().

◆ ast_cli_print_timestr_fromseconds()

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

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

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

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

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

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

Referenced by handle_cdr_pgsql_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 2431 of file main/cli.c.

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

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

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

◆ ast_cli_unregister_multiple()

int ast_cli_unregister_multiple ( struct ast_cli_entry e,
int  len 
)

Unregister multiple commands.

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

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

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

References ast_cli_unregister(), and len().

Referenced by cli_shutdown().

◆ ast_complete_channels()

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

Command completion for the list of active channels.

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

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

1863 {
1864  int wordlen = strlen(word), which = 0;
1865  struct ao2_container *cached_channels;
1866  char *ret = NULL;
1867  struct ao2_iterator iter;
1868  struct ast_channel_snapshot *snapshot;
1869 
1870  if (pos != rpos) {
1871  return NULL;
1872  }
1873 
1874  cached_channels = ast_channel_cache_all();
1875 
1876  iter = ao2_iterator_init(cached_channels, 0);
1877  for (; (snapshot = ao2_iterator_next(&iter)); ao2_ref(snapshot, -1)) {
1878  if (!strncasecmp(word, snapshot->base->name, wordlen) && (++which > state)) {
1879  if (state != -1) {
1880  ret = ast_strdup(snapshot->base->name);
1881  ao2_ref(snapshot, -1);
1882  break;
1883  }
1884 
1885  if (ast_cli_completion_add(ast_strdup(snapshot->base->name))) {
1886  ao2_ref(snapshot, -1);
1887  break;
1888  }
1889  }
1890  }
1891  ao2_iterator_destroy(&iter);
1892  ao2_ref(cached_channels, -1);
1893 
1894  return ret;
1895 }
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
enum sip_cc_notify_state state
Definition: chan_sip.c:966
struct ao2_container * ast_channel_cache_all(void)
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
const ast_string_field name
Structure representing a snapshot of channel state.
struct ast_channel_snapshot_base * base

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

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

◆ ast_debug_get_by_module()

unsigned int ast_debug_get_by_module ( const char *  module)

Get the debug level for a module.

Parameters
modulethe name of module
Returns
the debug level

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

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

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

◆ AST_THREADSTORAGE_RAW()

AST_THREADSTORAGE_RAW ( completion_storage  )

◆ ast_trace_get_by_module()

unsigned int ast_trace_get_by_module ( const char *  module)

Get the trace level for a module.

Parameters
modulethe name of module
Returns
the trace level

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

154 {
155  struct module_level *ml;
156  unsigned int res = 0;
157 
160  if (!strcasecmp(ml->module, module)) {
161  res = ml->level;
162  break;
163  }
164  }
166 
167  return res;
168 }
static struct module_level_list trace_modules
Definition: main/cli.c:108

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

◆ channel_set_debug()

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

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

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

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

Referenced by handle_core_set_debug_channel().

◆ cli_completion_vector_add()

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

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

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

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

Referenced by ast_cli_completion_add(), and ast_cli_completion_vector().

◆ cli_has_permissions()

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

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

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

2413 {
2414  struct ast_cli_entry *cur = NULL;
2415 
2416  while ((cur = cli_next(cur))) {
2417  if (cur == e) {
2418  return 1;
2419  }
2420  }
2421  return 0;
2422 }

References cli_next(), and NULL.

Referenced by __ast_cli_register().

◆ cli_next()

static struct ast_cli_entry* cli_next ( struct ast_cli_entry e)
static

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

962 {
963  if (e) {
964  return AST_LIST_NEXT(e, list);
965  } else {
966  return AST_LIST_FIRST(&helpers);
967  }
968 }
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:421
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439

References AST_LIST_FIRST, AST_LIST_NEXT, and ast_cli_entry::list.

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

◆ cli_shutdown()

static void cli_shutdown ( void  )
static

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

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

References ARRAY_LEN, ast_cli_unregister_multiple(), and cli_cli.

Referenced by ast_builtins_init().

◆ complete_number()

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

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

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

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

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

◆ destroy_user_perms()

static void destroy_user_perms ( void  )
static

cleanup (free) cli_perms linkedlist.

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

2100 {
2101  struct cli_perm *perm;
2102  struct usergroup_cli_perm *user_perm;
2103 
2105  while ((user_perm = AST_LIST_REMOVE_HEAD(&cli_perms, list))) {
2106  while ((perm = AST_LIST_REMOVE_HEAD(user_perm->perms, list))) {
2107  ast_free(perm->command);
2108  ast_free(perm);
2109  }
2110  ast_free(user_perm);
2111  }
2113 }
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
struct usergroup_cli_perm::@364 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 2394 of file main/cli.c.

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

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

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

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

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

◆ find_module_level()

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

Find the module level setting.

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

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

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

References AST_LIST_TRAVERSE, and NULL.

Referenced by handle_debug_or_trace().

◆ group_show_channels()

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

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

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

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

◆ handle_chanlist()

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

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

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

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

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

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

◆ handle_cli_malloc_trim()

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

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

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

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

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

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

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

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

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

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

◆ handle_commandmatchesarray()

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

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

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

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

◆ handle_core_reload()

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

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

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

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

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

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

Referenced by handle_nodebugchan_deprecated().

◆ handle_debug()

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

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

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

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

◆ handle_debug_category()

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

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

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

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

◆ handle_debug_or_trace()

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

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

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

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

Referenced by handle_debug(), and handle_trace().

◆ handle_help()

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

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

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

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

◆ handle_load()

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

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

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

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

◆ handle_logger_mute()

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

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

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

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

◆ handle_modlist()

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

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

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

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

◆ handle_nodebugchan_deprecated()

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

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

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

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

◆ handle_refresh()

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

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

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

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

◆ handle_reload()

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

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

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

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

◆ handle_showcalls()

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

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

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

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

◆ handle_showchan()

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

< Buffer for CDR variables.

< Accumulation buffer for all output.

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

1643 {
1644  struct ast_channel *chan;
1645  struct timeval now;
1646  char cdrtime[256];
1647  struct ast_str *obuf;/*!< Buffer for CDR variables. */
1648  struct ast_str *output;/*!< Accumulation buffer for all output. */
1649  long elapsed_seconds=0;
1650  int hour=0, min=0, sec=0;
1651  struct ast_var_t *var;
1652  struct ast_str *write_transpath = ast_str_alloca(256);
1653  struct ast_str *read_transpath = ast_str_alloca(256);
1654  struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
1655  struct ast_bridge *bridge;
1657  char callid_buf[32];
1658  int stream_num;
1659 
1660  switch (cmd) {
1661  case CLI_INIT:
1662  e->command = "core show channel";
1663  e->usage =
1664  "Usage: core show channel <channel>\n"
1665  " Shows lots of information about the specified channel.\n";
1666  return NULL;
1667  case CLI_GENERATE:
1668  return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
1669  }
1670 
1671  if (a->argc != 4) {
1672  return CLI_SHOWUSAGE;
1673  }
1674 
1675  obuf = ast_str_thread_get(&ast_str_thread_global_buf, 16);
1676  if (!obuf) {
1677  return CLI_FAILURE;
1678  }
1679 
1680  chan = ast_channel_get_by_name(a->argv[3]);
1681  if (!chan) {
1682  ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
1683 
1684  return CLI_SUCCESS;
1685  }
1686 
1687  output = ast_str_create(8192);
1688  if (!output) {
1689  ast_channel_unref(chan);
1690 
1691  return CLI_FAILURE;
1692  }
1693 
1694  now = ast_tvnow();
1695  ast_channel_lock(chan);
1696 
1697  if (!ast_tvzero(ast_channel_creationtime(chan))) {
1698  elapsed_seconds = now.tv_sec - ast_channel_creationtime(chan).tv_sec;
1699  hour = elapsed_seconds / 3600;
1700  min = (elapsed_seconds % 3600) / 60;
1701  sec = elapsed_seconds % 60;
1702  snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
1703  } else {
1704  strcpy(cdrtime, "N/A");
1705  }
1706 
1707  ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath);
1708  ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath);
1709 
1710  bridge = ast_channel_get_bridge(chan);
1711  callid_buf[0] = '\0';
1712  callid = ast_channel_callid(chan);
1713  if (callid) {
1714  ast_callid_strnprint(callid_buf, sizeof(callid_buf), callid);
1715  }
1716 
1717  ast_str_append(&output, 0,
1718  " -- General --\n"
1719  " Name: %s\n"
1720  " Type: %s\n"
1721  " UniqueID: %s\n"
1722  " LinkedID: %s\n"
1723  " Caller ID: %s\n"
1724  " Caller ID Name: %s\n"
1725  "Connected Line ID: %s\n"
1726  "Connected Line ID Name: %s\n"
1727  "Eff. Connected Line ID: %s\n"
1728  "Eff. Connected Line ID Name: %s\n"
1729  " DNID Digits: %s\n"
1730  " Language: %s\n"
1731  " State: %s (%u)\n"
1732  " NativeFormats: %s\n"
1733  " WriteFormat: %s\n"
1734  " ReadFormat: %s\n"
1735  " WriteTranscode: %s %s\n"
1736  " ReadTranscode: %s %s\n"
1737  " Time to Hangup: %ld\n"
1738  " Elapsed Time: %s\n"
1739  " Bridge ID: %s\n"
1740  " -- PBX --\n"
1741  " Context: %s\n"
1742  " Extension: %s\n"
1743  " Priority: %d\n"
1744  " Call Group: %llu\n"
1745  " Pickup Group: %llu\n"
1746  " Application: %s\n"
1747  " Data: %s\n"
1748  " Call Identifer: %s\n",
1749  ast_channel_name(chan),
1750  ast_channel_tech(chan)->type,
1751  ast_channel_uniqueid(chan),
1752  ast_channel_linkedid(chan),
1753  S_COR(ast_channel_caller(chan)->id.number.valid,
1754  ast_channel_caller(chan)->id.number.str, "(N/A)"),
1755  S_COR(ast_channel_caller(chan)->id.name.valid,
1756  ast_channel_caller(chan)->id.name.str, "(N/A)"),
1757  S_COR(ast_channel_connected(chan)->id.number.valid,
1758  ast_channel_connected(chan)->id.number.str, "(N/A)"),
1759  S_COR(ast_channel_connected(chan)->id.name.valid,
1760  ast_channel_connected(chan)->id.name.str, "(N/A)"),
1762  ast_channel_connected_effective_id(chan).number.str, "(N/A)"),
1764  ast_channel_connected_effective_id(chan).name.str, "(N/A)"),
1765  S_OR(ast_channel_dialed(chan)->number.str, "(N/A)"),
1766  ast_channel_language(chan),
1768  ast_channel_state(chan),
1772  ast_str_strlen(write_transpath) ? "Yes" : "No",
1773  ast_str_buffer(write_transpath),
1774  ast_str_strlen(read_transpath) ? "Yes" : "No",
1775  ast_str_buffer(read_transpath),
1776  (long)ast_channel_whentohangup(chan)->tv_sec,
1777  cdrtime,
1778  bridge ? bridge->uniqueid : "(Not bridged)",
1779  ast_channel_context(chan),
1780  ast_channel_exten(chan),
1781  ast_channel_priority(chan),
1782  ast_channel_callgroup(chan),
1784  S_OR(ast_channel_appl(chan), "(N/A)"),
1785  S_OR(ast_channel_data(chan), "(Empty)"),
1786  S_OR(callid_buf, "(None)")
1787  );
1788 
1789  ast_str_append(&output, 0, " Variables:\n");
1790 
1791  AST_LIST_TRAVERSE(ast_channel_varshead(chan), var, entries) {
1792  ast_str_append(&output, 0, "%s=%s\n", ast_var_name(var), ast_var_value(var));
1793  }
1794 
1795  if (!(ast_channel_tech(chan)->properties & AST_CHAN_TP_INTERNAL)
1796  && ast_cdr_serialize_variables(ast_channel_name(chan), &obuf, '=', '\n')) {
1797  ast_str_append(&output, 0, " CDR Variables:\n%s\n", ast_str_buffer(obuf));
1798  }
1799 
1800  ast_str_append(&output, 0, " -- Streams --\n");
1801  for (stream_num = 0; stream_num < ast_stream_topology_get_count(ast_channel_get_stream_topology(chan)); stream_num++) {
1803  struct ast_variable *metadata = ast_stream_get_metadata_list(stream);
1804 
1805  ast_str_append(&output, 0,
1806  "Name: %s\n"
1807  " Type: %s\n"
1808  " State: %s\n"
1809  " Group: %d\n"
1810  " Formats: %s\n"
1811  " Metadata:\n",
1812  ast_stream_get_name(stream),
1815  ast_stream_get_group(stream),
1817  );
1818 
1819  if (metadata) {
1820  struct ast_variable *v;
1821  for(v = metadata; v; v = v->next) {
1822  ast_str_append(&output, 0, " %s: %s\n", v->name, v->value);
1823  }
1824  ast_variables_destroy(metadata);
1825  }
1826  }
1827 
1828  ast_channel_unlock(chan);
1829 
1830  ast_cli(a->fd, "%s", ast_str_buffer(output));
1831  ast_free(output);
1832 
1833  ao2_cleanup(bridge);
1834  ast_channel_unref(chan);
1835 
1836  return CLI_SUCCESS;
1837 }
#define var
Definition: ast_expr2f.c:614
#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:3375
static const char type[]
Definition: chan_ooh323.c:109
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
const char * ast_channel_data(const struct ast_channel *chan)
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
Definition: channel.c:10720
ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan)
const char * ast_channel_context(const struct ast_channel *chan)
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
struct ast_trans_pvt * ast_channel_readtrans(const struct ast_channel *chan)
ast_callid ast_channel_callid(const struct ast_channel *chan)
struct timeval ast_channel_creationtime(struct ast_channel *chan)
const char * ast_channel_language(const struct ast_channel *chan)
const char * ast_channel_linkedid(const struct ast_channel *chan)
const char * ast_channel_exten(const struct ast_channel *chan)
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
@ AST_CHAN_TP_INTERNAL
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Definition: channel.h:971
struct ast_trans_pvt * ast_channel_writetrans(const 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)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
const char * ast_channel_appl(const struct ast_channel *chan)
struct varshead * ast_channel_varshead(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 timeval * ast_channel_whentohangup(struct ast_channel *chan)
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:60
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:80
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:347
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:324
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:734
static const char name[]
Definition: format_mp3.c:68
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
void ast_callid_strnprint(char *buffer, size_t buffer_size, ast_callid callid)
copy a string representation of the callid into a target string
Definition: logger.c:2038
unsigned int ast_callid
struct ast_variable * ast_stream_get_metadata_list(const struct ast_stream *stream)
Get all stream metadata keys.
Definition: stream.c:439
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
int ast_stream_get_group(const struct ast_stream *stream)
Get the stream group that a stream is part of.
Definition: stream.c:1077
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
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
const char * ast_stream_state2str(enum ast_stream_state state)
Convert the state of a stream into a string.
Definition: stream.c:388
const char * ast_stream_get_name(const struct ast_stream *stream)
Get the name of a stream.
Definition: stream.c:309
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:1117
#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:826
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:640
Structure that contains information about a bridge.
Definition: bridge.h:349
ast_callid callid
Definition: bridge.h:361
const ast_string_field uniqueid
Definition: bridge.h:401
Number structure.
Definition: app_followme.c:154
const char * ast_translate_path_to_str(struct ast_trans_pvt *t, struct ast_str **str)
Puts a string representation of the translation path into outbuf.
Definition: translate.c:928

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

◆ handle_showuptime()

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

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

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

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

◆ handle_softhangup()

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

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

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

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

◆ handle_trace()

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

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

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

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

◆ handle_unload()

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

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

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

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

◆ handle_verbose()

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

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

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

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

◆ help1()

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

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

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

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

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

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

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

Referenced by __ast_cli_generator().

◆ modlist_modentry()

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

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

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

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

2851 {
2852  int i;
2853  for (i = 0; dst[i]; i++) {
2854  if (dst[i][0] != '[')
2855  return -1;
2856  }
2857  return 0;
2858 }

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

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

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

Referenced by __ast_cli_generator(), and ast_cli_command_full().

◆ print_uptimestr()

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

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

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

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

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

◆ remove_shutdown_command()

static void remove_shutdown_command ( struct ast_cli_entry e)
static

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

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

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

Referenced by ast_cli_unregister().

◆ set_full_cmd()

static int set_full_cmd ( struct ast_cli_entry e)
static

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

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

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

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

Referenced by __ast_cli_register().

◆ status_debug_verbose()

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

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

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

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

Referenced by handle_debug_or_trace(), and handle_verbose().

◆ word_match()

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

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

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

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

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

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

Referenced by __ast_cli_generator(), and find_cli().

Variable Documentation

◆ ast_cli_buf

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

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

Referenced by ast_cli().

◆ cli_cli

struct ast_cli_entry cli_cli[]
static

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

Referenced by ast_builtins_init(), and cli_shutdown().

◆ cli_default_perm

int cli_default_perm = 1
static

Default permissions value 1=Permit 0=Deny.

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

Referenced by ast_cli_perms_init(), and cli_has_permissions().

◆ cli_perms

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

◆ cli_rsvd

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

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

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

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

◆ climodentryfd

int climodentryfd = -1
static

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

Referenced by handle_modlist(), and modlist_modentry().

◆ climodentrylock

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

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

Referenced by handle_modlist().

◆ current

size_t current

◆ debug_modules

struct module_level_list debug_modules = AST_RWLIST_HEAD_INIT_VALUE
static

lists of module names and their debug/trace levels

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

Referenced by ast_debug_get_by_module(), and handle_debug_or_trace().

◆ elems

struct ast_cli_entry* * elems

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

◆ helpers

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

◆ max

size_t max

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

Referenced by complete_number(), and parse_args().

◆ perms_config

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

CLI permissions config file.

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

Referenced by ast_cli_perms_init().

◆ permsconfiglock

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

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

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

Referenced by ast_cli_perms_init().

◆ 

struct { ... } shutdown_commands

◆ shutdown_commands_lock

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

◆ trace_modules

struct module_level_list trace_modules = AST_RWLIST_HEAD_INIT_VALUE
static

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

Referenced by ast_trace_get_by_module(), and handle_debug_or_trace().