Sun Oct 16 2011 08:42:42

Asterisk developer's documentation


cli.c File Reference

Standard Command Line Interface. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <sys/signal.h>
#include <signal.h>
#include <ctype.h>
#include <regex.h>
#include <pwd.h>
#include <grp.h>
#include <readline.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/translate.h"
Include dependency graph for 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...

Defines

#define AST_CLI_INITLEN   256
 Initial buffer size for resulting strings in ast_cli()
#define CONCISE_FORMAT_STRING   "%s!%s!%s!%d!%s!%s!%s!%s!%s!%s!%d!%s!%s!%s\n"
#define DAY   (HOUR*24)
#define 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\n"
#define MODLIST_FORMAT2   "%-30s %-40.40s %-10s\n"
#define NEEDCOMMA(x)   ((x)? ",": "")
#define SECOND   (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 WEEK   (DAY*7)
#define YEAR   (DAY*365)

Functions

static char * __ast_cli_generator (const char *text, const char *word, int state, int lock)
static int __ast_cli_register (struct ast_cli_entry *e, struct ast_cli_entry *ed)
static int __ast_cli_unregister (struct ast_cli_entry *e, struct ast_cli_entry *ed)
static void __init_ast_cli_buf (void)
void ast_builtins_init (void)
 initialize the _full_cmd string in * each of the builtins.
void ast_cli (int fd, const char *fmt,...)
int ast_cli_command_full (int uid, int gid, int fd, const char *s)
 Interprets a command Interpret a command s, sending output to fd if uid:gid has permissions to run this command. uid = CLI_NO_PERMS to avoid checking user permissions gid = CLI_NO_PERMS to avoid checking group permissions.
int ast_cli_command_multiple_full (int uid, int gid, int fd, size_t size, const char *s)
 Executes multiple CLI commands Interpret strings separated by NULL and execute each one, sending output to fd if uid has permissions, uid = CLI_NO_PERMS to avoid checking users permissions. gid = CLI_NO_PERMS to avoid checking group permissions.
char * ast_cli_complete (const char *word, const char *const choices[], int state)
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.
char * ast_cli_generator (const char *text, const char *word, int state)
 Readline madness Useful for readline, that's about it.
int ast_cli_generatornummatches (const char *text, const char *word)
 Return the number of unique matches for the generator.
int ast_cli_perms_init (int reload)
int ast_cli_register (struct ast_cli_entry *e)
 Registers a command or an array of commands.
int ast_cli_register_multiple (struct ast_cli_entry *e, int len)
 Register multiple commands.
int ast_cli_unregister (struct ast_cli_entry *e)
 Unregisters a command or an array of commands.
int ast_cli_unregister_multiple (struct ast_cli_entry *e, int len)
 Unregister multiple commands.
char * ast_complete_channels (const char *line, const char *word, int pos, int state, int rpos)
 Command completion for the list of active channels.
unsigned int ast_debug_get_by_module (const char *module)
 Get the debug level for a module.
unsigned int ast_verbose_get_by_module (const char *module)
 Get the verbose level for a module.
static int channel_set_debug (void *obj, void *arg, void *data, int flags)
static int cli_has_permissions (int uid, int gid, const char *command)
static struct ast_cli_entrycli_next (struct ast_cli_entry *e)
static char * complete_fn (const char *word, int state)
static char * complete_number (const char *partial, unsigned int min, unsigned int max, int n)
static void destroy_user_perms (void)
 cleanup (free) cli_perms linkedlist.
static char * find_best (const char *argv[])
static struct ast_cli_entryfind_cli (const char *const cmds[], int match_type)
static struct module_levelfind_module_level (const char *module, unsigned int debug)
 Find the debug or verbose file setting.
static char * group_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_chanlist (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_check_permissions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handles CLI command 'cli check permissions'
static char * handle_cli_reload_permissions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handles CLI command 'cli reload permissions'
static char * handle_cli_show_permissions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handles CLI command 'cli show permissions'
static char * handle_cli_wait_fullybooted (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_commandcomplete (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_commandnummatches (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_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_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_unload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_verbose (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * help1 (int fd, const char *const match[], int locked)
 helper for final part of handle_help if locked = 1, assume the list is already locked
static char * is_prefix (const char *word, const char *token, int pos, int *actual)
 if word is a valid prefix for token, returns the pos-th match as a malloced string, or NULL otherwise. Always tell in *actual how many matches we got.
static int modlist_modentry (const char *module, const char *description, int usecnt, const char *like)
static int more_words (const char *const *dst)
 returns true if there are more words to match
static char * parse_args (const char *s, int *argc, const char *argv[], int max, int *trailingwhitespace)
static void print_uptimestr (int fd, struct timeval timeval, const char *prefix, int printsec)
static int set_full_cmd (struct ast_cli_entry *e)
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.
static struct cli_perms cli_perms
static const char cli_rsvd [] = "[]{}|*%"
static int climodentryfd = -1
static ast_mutex_t climodentrylock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static struct module_level_list debug_modules
static struct helpers helpers
static const char perms_config [] = "cli_permissions.conf"
 CLI permissions config file.
static ast_mutex_t permsconfiglock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
 mutex used to prevent a user from running the 'cli reload permissions' command while it is already running.
static struct module_level_list verbose_modules

Detailed Description

Standard Command Line Interface.

Author:
Mark Spencer <markster@digium.com>

Definition in file cli.c.


Define Documentation

#define AST_CLI_INITLEN   256

Initial buffer size for resulting strings in ast_cli()

Definition at line 100 of file cli.c.

Referenced by ast_cli().

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

Referenced by handle_chanlist().

#define DAY   (HOUR*24)

Referenced by print_uptimestr().

#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"

Referenced by handle_chanlist().

#define HOUR   (MINUTE*60)

Referenced by print_uptimestr().

#define MINUTE   (SECOND*60)

Referenced by print_uptimestr().

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

Definition at line 642 of file cli.c.

Referenced by modlist_modentry().

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

Definition at line 643 of file cli.c.

Referenced by handle_modlist().

#define NEEDCOMMA (   x)    ((x)? ",": "")

Referenced by print_uptimestr().

#define SECOND   (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"

Referenced by handle_chanlist().

#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"

Referenced by handle_chanlist().

#define WEEK   (DAY*7)

Referenced by print_uptimestr().

#define YEAR   (DAY*365)

Referenced by print_uptimestr().


Function Documentation

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

Definition at line 2360 of file cli.c.

References AST_MAX_ARGS, parse_args(), ARRAY_LEN, ast_strlen_zero(), ast_join(), AST_RWLIST_RDLOCK, cli_next(), ast_cli_entry::command, word_match(), ast_cli_entry::cmda, more_words(), is_prefix(), ast_free, ast_cli_entry::handler, ast_cli_args::line, word, ast_cli_args::argv, CLI_GENERATE, and AST_RWLIST_UNLOCK.

Referenced by handle_commandcomplete(), handle_help(), and ast_cli_generator().

{
   const char *argv[AST_MAX_ARGS];
   struct ast_cli_entry *e = NULL;
   int x = 0, argindex, matchlen;
   int matchnum=0;
   char *ret = NULL;
   char matchstr[80] = "";
   int tws = 0;
   /* Split the argument into an array of words */
   char *duplicate = parse_args(text, &x, argv, ARRAY_LEN(argv), &tws);

   if (!duplicate)   /* malloc error */
      return NULL;

   /* Compute the index of the last argument (could be an empty string) */
   argindex = (!ast_strlen_zero(word) && x>0) ? x-1 : x;

   /* rebuild the command, ignore terminating white space and flatten space */
   ast_join(matchstr, sizeof(matchstr)-1, argv);
   matchlen = strlen(matchstr);
   if (tws) {
      strcat(matchstr, " "); /* XXX */
      if (matchlen)
         matchlen++;
   }
   if (lock)
      AST_RWLIST_RDLOCK(&helpers);
   while ( (e = cli_next(e)) ) {
      /* XXX repeated code */
      int src = 0, dst = 0, n = 0;

      if (e->command[0] == '_')
         continue;

      /*
       * Try to match words, up to and excluding the last word, which
       * is either a blank or something that we want to extend.
       */
      for (;src < argindex; dst++, src += n) {
         n = word_match(argv[src], e->cmda[dst]);
         if (n < 0)
            break;
      }

      if (src != argindex && more_words(e->cmda + dst))  /* not a match */
         continue;
      ret = is_prefix(argv[src], e->cmda[dst], state - matchnum, &n);
      matchnum += n; /* this many matches here */
      if (ret) {
         /*
          * argv[src] is a valid prefix of the next word in this
          * command. If this is also the correct entry, return it.
          */
         if (matchnum > state)
            break;
         ast_free(ret);
         ret = NULL;
      } else if (ast_strlen_zero(e->cmda[dst])) {
         /*
          * This entry is a prefix of the command string entered
          * (only one entry in the list should have this property).
          * Run the generator if one is available. In any case we are done.
          */
         if (e->handler) { /* new style command */
            struct ast_cli_args a = {
               .line = matchstr, .word = word,
               .pos = argindex,
               .n = state - matchnum,
               .argv = argv,
               .argc = x};
            ret = e->handler(e, CLI_GENERATE, &a);
         }
         if (ret)
            break;
      }
   }
   if (lock)
      AST_RWLIST_UNLOCK(&helpers);
   ast_free(duplicate);
   return ret;
}
static int __ast_cli_register ( struct ast_cli_entry e,
struct ast_cli_entry ed 
) [static]

Definition at line 2047 of file cli.c.

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

Referenced by ast_cli_register().

{
   struct ast_cli_entry *cur;
   int i, lf, ret = -1;

   struct ast_cli_args a;  /* fake argument */
   char **dst = (char **)e->cmda;   /* need to cast as the entry is readonly */
   char *s;

   memset(&a, '\0', sizeof(a));
   e->handler(e, CLI_INIT, &a);
   /* XXX check that usage and command are filled up */
   s = ast_skip_blanks(e->command);
   s = e->command = ast_strdup(s);
   for (i=0; !ast_strlen_zero(s) && i < AST_MAX_CMD_LEN-1; i++) {
      *dst++ = s; /* store string */
      s = ast_skip_nonblanks(s);
      if (*s == '\0')   /* we are done */
         break;
      *s++ = '\0';
      s = ast_skip_blanks(s);
   }
   *dst++ = NULL;
   
   AST_RWLIST_WRLOCK(&helpers);
   
   if (find_cli(e->cmda, 1)) {
      ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n", S_OR(e->_full_cmd, e->command));
      goto done;
   }
   if (set_full_cmd(e))
      goto done;

   lf = e->cmdlen;
   AST_RWLIST_TRAVERSE_SAFE_BEGIN(&helpers, cur, list) {
      int len = cur->cmdlen;
      if (lf < len)
         len = lf;
      if (strncasecmp(e->_full_cmd, cur->_full_cmd, len) < 0) {
         AST_RWLIST_INSERT_BEFORE_CURRENT(e, list); 
         break;
      }
   }
   AST_RWLIST_TRAVERSE_SAFE_END;

   if (!cur)
      AST_RWLIST_INSERT_TAIL(&helpers, e, list); 
   ret = 0; /* success */

done:
   AST_RWLIST_UNLOCK(&helpers);

   return ret;
}
static int __ast_cli_unregister ( struct ast_cli_entry e,
struct ast_cli_entry ed 
) [static]

Definition at line 2025 of file cli.c.

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

Referenced by ast_cli_unregister().

{
   if (e->inuse) {
      ast_log(LOG_WARNING, "Can't remove command that is in use\n");
   } else {
      AST_RWLIST_WRLOCK(&helpers);
      AST_RWLIST_REMOVE(&helpers, e, list);
      AST_RWLIST_UNLOCK(&helpers);
      ast_free(e->_full_cmd);
      e->_full_cmd = NULL;
      if (e->handler) {
         /* this is a new-style entry. Reset fields and free memory. */
         char *cmda = (char *) e->cmda;
         memset(cmda, '\0', sizeof(e->cmda));
         ast_free(e->command);
         e->command = NULL;
         e->usage = NULL;
      }
   }
   return 0;
}
static void __init_ast_cli_buf ( void  ) [static]

Definition at line 97 of file cli.c.

{
void ast_builtins_init ( void  )

initialize the _full_cmd string in * each of the builtins.

Provided by cli.c

Definition at line 1858 of file cli.c.

References ast_cli_register_multiple(), and ARRAY_LEN.

Referenced by main().

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

Definition at line 102 of file cli.c.

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

Referenced by aoc_cli_debug_enable(), meetme_show_cmd(), meetme_cmd(), sla_show_trunks(), sla_show_stations(), handle_minivm_list_templates(), handle_minivm_show_users(), handle_minivm_show_zones(), handle_minivm_show_settings(), handle_minivm_show_stats(), handle_minivm_reload(), handle_cli_mixmonitor(), handle_cli_osp_show(), __say_cli_init(), do_print(), handle_queue_add_member(), handle_queue_remove_member(), handle_queue_pause_member(), handle_queue_set_member_penalty(), handle_queue_rule_show(), rpt_do_debug(), rpt_do_dump(), rpt_do_stats(), rpt_do_lstats(), rpt_do_nodes(), rpt_do_local_nodes(), rpt_do_fun(), rpt_do_cmd(), show_users_realtime(), handle_voicemail_show_users(), handle_voicemail_show_zones(), handle_voicemail_reload(), handle_show_settings(), handle_show_threads(), handle_show_sysinfo(), handle_show_profile(), handle_show_version_files(), ast_console_toggle_mute(), handle_version(), handle_stop_when_convenient(), handle_restart_when_convenient(), show_warranty(), show_license(), cc_cli_print_monitor_stats(), print_stats_cb(), cc_cli_output_status(), handle_cli_status(), handle_cli_submit(), print_app(), print_cel_sub(), agent_logoff_cmd(), agents_show(), agents_show_online(), console_autoanswer(), console_answer(), console_sendtext(), console_hangup(), console_dial(), console_mute(), cli_console_autoanswer(), cli_console_flash(), cli_console_dial(), cli_console_hangup(), cli_console_mute(), cli_list_available(), cli_list_devices(), cli_console_answer(), cli_console_sendtext(), cli_console_active(), handle_pri_set_debug_file(), handle_pri_debug(), handle_pri_show_span(), handle_pri_show_debug(), handle_pri_version(), dahdi_show_channels(), dahdi_show_channel(), handle_dahdi_show_cadences(), dahdi_show_status(), dahdi_show_version(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_set_dnd(), handle_ss7_debug(), handle_ss7_block_cic(), handle_ss7_block_linkset(), handle_ss7_unblock_cic(), handle_ss7_unblock_linkset(), handle_ss7_show_linkset(), handle_ss7_version(), gtalk_show_channels(), handle_cli_h323_set_trace(), handle_cli_h323_set_debug(), handle_cli_iax2_show_callno_limits(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_show_peer(), handle_cli_iax2_show_stats(), handle_cli_iax2_set_mtu(), handle_cli_iax2_show_cache(), handle_cli_iax2_show_users(), __iax2_show_peers(), handle_cli_iax2_show_threads(), handle_cli_iax2_unregister(), handle_cli_iax2_show_firmware(), handle_cli_iax2_show_registry(), handle_cli_iax2_show_channels(), ast_cli_netstats(), handle_cli_iax2_show_netstats(), handle_cli_iax2_set_debug(), handle_cli_iax2_set_debug_trunk(), handle_cli_iax2_set_debug_jb(), handle_cli_iax2_provision(), jingle_show_channels(), locals_show(), handle_mgcp_show_endpoints(), handle_mgcp_audit_endpoint(), handle_mgcp_set_debug(), handle_cli_misdn_set_debug(), show_config_description(), handle_cli_misdn_show_config(), handle_cli_misdn_reload(), print_bc_info(), handle_cli_misdn_show_channels(), handle_cli_misdn_show_stacks(), handle_cli_misdn_show_ports_stats(), handle_cli_misdn_show_port(), handle_cli_misdn_send_digit(), handle_cli_misdn_toggle_echocancel(), handle_cli_misdn_send_display(), console_cmd(), console_do_answer(), console_flash(), console_transfer(), console_active(), console_boost(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), _sip_show_peers(), peer_dump_func(), dialog_dump_func(), sip_show_objects(), print_group(), sip_prune_realtime(), print_codec_to_cli(), sip_show_domains(), _sip_qualify_peer(), _sip_show_peer(), sip_show_user(), sip_show_sched(), sip_show_registry(), sip_unregister(), show_chanstats_cb(), sip_show_channelstats(), sip_show_settings(), sip_show_mwi(), show_channels_cb(), sip_show_channels(), sip_show_channel(), sip_show_history(), sip_do_debug_ip(), sip_do_debug_peer(), sip_do_debug(), sip_cli_notify(), sip_set_history(), handle_skinny_set_debug(), _skinny_show_devices(), _skinny_show_device(), _skinny_show_lines(), _skinny_show_line(), handle_skinny_show_settings(), unistim_info(), unistim_sp(), unistim_do_debug(), radio_tune(), radio_set_debug(), radio_set_debug_off(), radio_active(), radio_set_xpmr_debug(), tune_txoutput(), tune_rxinput(), tune_rxvoice(), tune_rxctcss(), handle_cli_core_show_channeltypes(), handle_cli_core_show_channeltype(), handle_load(), handle_reload(), handle_verbose(), handle_unload(), modlist_modentry(), print_uptimestr(), handle_modlist(), handle_showcalls(), handle_chanlist(), handle_softhangup(), handle_cli_show_permissions(), handle_cli_check_permissions(), handle_commandmatchesarray(), handle_commandnummatches(), handle_commandcomplete(), channel_set_debug(), handle_core_set_debug_channel(), handle_showchan(), group_show_channels(), handle_cli_wait_fullybooted(), help1(), handle_help(), ast_cli_command_full(), ais_clm_show_members(), handle_cli_transcoder_show(), handle_cli_core_show_config_mappings(), handle_cli_config_list(), data_result_print_cli_node(), data_result_print_cli(), data_provider_print_cli(), handle_cli_database_put(), handle_cli_database_get(), handle_cli_database_del(), handle_cli_database_deltree(), db_show_cb(), handle_cli_database_show(), db_showkey_cb(), handle_cli_database_showkey(), handle_cli_refresh(), dump_raw_ie(), event_dump_cli(), event_dump_cache(), ais_evt_show_event_channels(), handle_feature_show(), handle_parkedcalls(), handle_cli_core_show_file_formats(), show_codecs(), show_codec_n(), handle_cli_devstate_list(), handle_cli_devstate_change(), cli_odbc_read(), cli_odbc_write(), handle_show_http(), iax_show_provisioning(), handle_core_show_image_formats(), handle_cli_indication_show(), handle_logger_reload(), handle_logger_rotate(), handle_logger_set_level(), handle_logger_show_channels(), handle_showmancmd(), handle_mandebug(), handle_showmanager(), handle_showmanagers(), handle_showmancmds(), handle_showmanconn(), handle_showmaneventq(), handle_manager_show_settings(), cli_match_char_tree(), handle_show_functions(), handle_show_function(), print_app_docs(), handle_show_application(), handle_show_hints(), handle_show_hint(), handle_show_switches(), handle_show_applications(), show_dialplan_helper(), show_debug_helper(), handle_show_dialplan(), handle_debug_dialplan(), handle_show_globals(), handle_show_chanvar(), handle_set_global(), handle_set_chanvar(), handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), handle_cli_dialplan_remove_include(), handle_cli_dialplan_remove_extension(), handle_cli_dialplan_add_include(), handle_cli_dialplan_save(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_add_ignorepat(), handle_cli_dialplan_remove_ignorepat(), handle_cli_dialplan_reload(), dundi_set_debug(), dundi_store_history(), dundi_flush(), dundi_do_lookup(), dundi_do_precache(), dundi_do_query(), dundi_show_peer(), dundi_show_peers(), dundi_show_trans(), dundi_show_entityid(), dundi_show_requests(), dundi_show_mappings(), dundi_show_precache(), handle_cli_agi_add_cmd(), handle_cli_agi_debug(), help_workhorse(), handle_cli_agi_show(), handle_cli_agi_dump_html(), handle_show_calendars(), handle_show_calendar(), alias_show(), orig_app(), orig_exten(), handle_redirect(), realtime_ldap_status(), handle_cli_realtime_pgsql_cache(), handle_cli_realtime_pgsql_status(), handle_cli_show_sqlite_status(), handle_cli_sqlite_show_tables(), handle_cli_file_convert(), handle_cli_keys_show(), cli_fax_show_version(), cli_fax_set_debug(), cli_fax_show_capabilities(), cli_fax_show_settings(), cli_fax_show_session(), cli_fax_show_stats(), cli_fax_show_sessions(), spandsp_fax_cli_show_capabilities(), spandsp_fax_cli_show_session(), spandsp_fax_cli_show_stats(), aji_cli_list_pubsub_nodes(), aji_cli_purge_pubsub_nodes(), aji_cli_delete_pubsub_node(), aji_cli_create_collection(), aji_cli_create_leafnode(), aji_do_set_debug(), aji_do_reload(), aji_show_clients(), aji_show_buddies(), aji_test(), handle_cli_ulimit(), handle_cli_moh_show_files(), handle_cli_moh_show_classes(), handle_cli_odbc_show(), handle_show_routes(), pktccops_show_cmtses(), pktccops_show_gates(), pktccops_show_pools(), pktccops_gatedel(), pktccops_gateset(), pktccops_debug(), cli_realtime_load(), cli_realtime_update(), cli_realtime_update2(), cli_realtime_store(), cli_realtime_destroy(), rtp_do_debug_ip(), rtcp_do_debug_ip(), handle_cli_rtp_set_debug(), handle_cli_rtcp_set_debug(), handle_cli_rtcp_set_stats(), sig_pri_cli_show_channels_header(), sig_pri_cli_show_channels(), sig_pri_cli_show_spans(), sig_pri_cli_show_span(), handle_cli_stun_set_debug(), cli_tps_ping(), cli_tps_report(), timing_test(), handle_cli_core_show_translation(), and handle_cli_udptl_set_debug().

{
   int res;
   struct ast_str *buf;
   va_list ap;

   if (!(buf = ast_str_thread_get(&ast_cli_buf, AST_CLI_INITLEN)))
      return;

   va_start(ap, fmt);
   res = ast_str_set_va(&buf, 0, fmt, ap);
   va_end(ap);

   if (res != AST_DYNSTR_BUILD_FAILED) {
      ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100);
   }
}
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 2448 of file cli.c.

References args, AST_MAX_ARGS, parse_args(), ast_cli_args::fd, AST_RWLIST_RDLOCK, find_cli(), ast_atomic_fetchadd_int(), ast_cli_entry::inuse, AST_RWLIST_UNLOCK, ast_cli(), find_best(), ast_join(), cli_has_permissions(), ast_free, ast_cli_entry::handler, CLI_HANDLER, CLI_SHOWUSAGE, S_OR, ast_cli_entry::usage, and CLI_FAILURE.

Referenced by ast_cli_command_multiple_full().

{
   const char *args[AST_MAX_ARGS + 1];
   struct ast_cli_entry *e;
   int x;
   char *duplicate = parse_args(s, &x, args + 1, AST_MAX_ARGS, NULL);
   char tmp[AST_MAX_ARGS + 1];
   char *retval = NULL;
   struct ast_cli_args a = {
      .fd = fd, .argc = x, .argv = args+1 };

   if (duplicate == NULL)
      return -1;

   if (x < 1)  /* We need at least one entry, otherwise ignore */
      goto done;

   AST_RWLIST_RDLOCK(&helpers);
   e = find_cli(args + 1, 0);
   if (e)
      ast_atomic_fetchadd_int(&e->inuse, 1);
   AST_RWLIST_UNLOCK(&helpers);
   if (e == NULL) {
      ast_cli(fd, "No such command '%s' (type 'core show help %s' for other possible commands)\n", s, find_best(args + 1));
      goto done;
   }

   ast_join(tmp, sizeof(tmp), args + 1);
   /* Check if the user has rights to run this command. */
   if (!cli_has_permissions(uid, gid, tmp)) {
      ast_cli(fd, "You don't have permissions to run '%s' command\n", tmp);
      ast_free(duplicate);
      return 0;
   }

   /*
    * Within the handler, argv[-1] contains a pointer to the ast_cli_entry.
    * Remember that the array returned by parse_args is NULL-terminated.
    */
   args[0] = (char *)e;

   retval = e->handler(e, CLI_HANDLER, &a);

   if (retval == CLI_SHOWUSAGE) {
      ast_cli(fd, "%s", S_OR(e->usage, "Invalid usage, but no usage information available.\n"));
   } else {
      if (retval == CLI_FAILURE)
         ast_cli(fd, "Command '%s' failed.\n", s);
   }
   ast_atomic_fetchadd_int(&e->inuse, -1);
done:
   ast_free(duplicate);
   return 0;
}
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
Return values:
numberof commands executed

Definition at line 2503 of file cli.c.

References ast_cli_command_full().

Referenced by netconsole().

{
   char cmd[512];
   int x, y = 0, count = 0;

   for (x = 0; x < size; x++) {
      cmd[y] = s[x];
      y++;
      if (s[x] == '\0') {
         ast_cli_command_full(uid, gid, fd, cmd);
         y = 0;
         count++;
      }
   }
   return count;
}
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;
    }

Definition at line 1518 of file cli.c.

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

Referenced by complete_meetmecmd(), handle_cc_kill(), handle_cli_iax2_prune_realtime(), sip_prune_realtime(), event_dump_cache(), handle_cli_devstate_change(), handle_show_applications(), handle_orig(), and handle_cli_core_show_translation().

{
   int i, which = 0, len;
   len = ast_strlen_zero(word) ? 0 : strlen(word);

   for (i = 0; choices[i]; i++) {
      if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state)
         return ast_strdup(choices[i]);
   }
   return NULL;
}
char** ast_cli_completion_matches ( const char *  ,
const char *   
)

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.

Definition at line 2299 of file cli.c.

References ast_cli_generator(), ast_realloc, ast_malloc, and ast_copy_string().

Referenced by cli_complete(), and handle_commandmatchesarray().

{
   char **match_list = NULL, *retstr, *prevstr;
   size_t match_list_len, max_equal, which, i;
   int matches = 0;

   /* leave entry 0 free for the longest common substring */
   match_list_len = 1;
   while ((retstr = ast_cli_generator(text, word, matches)) != NULL) {
      if (matches + 1 >= match_list_len) {
         match_list_len <<= 1;
         if (!(match_list = ast_realloc(match_list, match_list_len * sizeof(*match_list))))
            return NULL;
      }
      match_list[++matches] = retstr;
   }

   if (!match_list)
      return match_list; /* NULL */

   /* Find the longest substring that is common to all results
    * (it is a candidate for completion), and store a copy in entry 0.
    */
   prevstr = match_list[1];
   max_equal = strlen(prevstr);
   for (which = 2; which <= matches; which++) {
      for (i = 0; i < max_equal && toupper(prevstr[i]) == toupper(match_list[which][i]); i++)
         continue;
      max_equal = i;
   }

   if (!(retstr = ast_malloc(max_equal + 1)))
      return NULL;
   
   ast_copy_string(retstr, match_list[1], max_equal + 1);
   match_list[0] = retstr;

   /* ensure that the array is NULL terminated */
   if (matches + 1 >= match_list_len) {
      if (!(match_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(*match_list))))
         return NULL;
   }
   match_list[matches + 1] = NULL;

   return match_list;
}
char* ast_cli_generator ( const char *  ,
const char *  ,
int   
)

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

Return values:
0on success
-1on failure

Definition at line 2443 of file cli.c.

References __ast_cli_generator().

Referenced by handle_cli_check_permissions(), ast_cli_generatornummatches(), ast_cli_completion_matches(), and cli_alias_passthrough().

{
   return __ast_cli_generator(text, word, state, 1);
}
int ast_cli_generatornummatches ( const char *  text,
const char *  word 
)

Return the number of unique matches for the generator.

Definition at line 2282 of file cli.c.

References ast_cli_generator(), and ast_free.

Referenced by handle_commandnummatches().

{
   int matches = 0, i = 0;
   char *buf = NULL, *oldbuf = NULL;

   while ((buf = ast_cli_generator(text, word, i++))) {
      if (!oldbuf || strcmp(buf,oldbuf))
         matches++;
      if (oldbuf)
         ast_free(oldbuf);
      oldbuf = buf;
   }
   if (oldbuf)
      ast_free(oldbuf);
   return matches;
}
int ast_cli_perms_init ( int  reload)

Provided by cli.c

Definition at line 1735 of file cli.c.

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

Referenced by main(), and handle_cli_reload_permissions().

{
   struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
   struct ast_config *cfg;
   char *cat = NULL;
   struct ast_variable *v;
   struct usergroup_cli_perm *user_group, *cp_entry;
   struct cli_perm *perm = NULL;
   struct passwd *pw;
   struct group *gr;

   if (ast_mutex_trylock(&permsconfiglock)) {
      ast_log(LOG_NOTICE, "You must wait until last 'cli reload permissions' command finish\n");
      return 1;
   }

   cfg = ast_config_load2(perms_config, "" /* core, can't reload */, config_flags);
   if (!cfg) {
      ast_mutex_unlock(&permsconfiglock);
      return 1;
   } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
      ast_mutex_unlock(&permsconfiglock);
      return 0;
   }

   /* free current structures. */
   destroy_user_perms();

   while ((cat = ast_category_browse(cfg, cat))) {
      if (!strcasecmp(cat, "general")) {
         /* General options */
         for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
            if (!strcasecmp(v->name, "default_perm")) {
               cli_default_perm = (!strcasecmp(v->value, "permit")) ? 1: 0;
            }
         }
         continue;
      }

      /* users or groups */
      gr = NULL, pw = NULL;
      if (cat[0] == '@') {
         /* This is a group */
         gr = getgrnam(&cat[1]);
         if (!gr) {
            ast_log (LOG_WARNING, "Unknown group '%s'\n", &cat[1]);
            continue;
         }
      } else {
         /* This is a user */
         pw = getpwnam(cat);
         if (!pw) {
            ast_log (LOG_WARNING, "Unknown user '%s'\n", cat);
            continue;
         }
      }
      user_group = NULL;
      /* Check for duplicates */
      AST_RWLIST_WRLOCK(&cli_perms);
      AST_LIST_TRAVERSE(&cli_perms, cp_entry, list) {
         if ((pw && cp_entry->uid == pw->pw_uid) || (gr && cp_entry->gid == gr->gr_gid)) {
            /* if it is duplicated, just added this new settings, to 
            the current list. */
            user_group = cp_entry;
            break;
         }
      }
      AST_RWLIST_UNLOCK(&cli_perms);

      if (!user_group) {
         /* alloc space for the new user config. */
         user_group = ast_calloc(1, sizeof(*user_group));
         if (!user_group) {
            continue;
         }
         user_group->uid = (pw ? pw->pw_uid : -1);
         user_group->gid = (gr ? gr->gr_gid : -1);
         user_group->perms = ast_calloc(1, sizeof(*user_group->perms));
         if (!user_group->perms) {
            ast_free(user_group);
            continue;
         }
      }
      for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
         if (ast_strlen_zero(v->value)) {
            /* we need to check this condition cause it could break security. */
            ast_log(LOG_WARNING, "Empty permit/deny option in user '%s'\n", cat);
            continue;
         }
         if (!strcasecmp(v->name, "permit")) {
            perm = ast_calloc(1, sizeof(*perm));
            if (perm) {
               perm->permit = 1;
               perm->command = ast_strdup(v->value);
            }
         } else if (!strcasecmp(v->name, "deny")) {
            perm = ast_calloc(1, sizeof(*perm));
            if (perm) {
               perm->permit = 0;
               perm->command = ast_strdup(v->value);
            }
         } else {
            /* up to now, only 'permit' and 'deny' are possible values. */
            ast_log(LOG_WARNING, "Unknown '%s' option\n", v->name);
            continue;
         }
         if (perm) {
            /* Added the permission to the user's list. */
            AST_LIST_INSERT_TAIL(user_group->perms, perm, list);
            perm = NULL;
         }
      }
      AST_RWLIST_WRLOCK(&cli_perms);
      AST_RWLIST_INSERT_TAIL(&cli_perms, user_group, list);
      AST_RWLIST_UNLOCK(&cli_perms);
   }

   ast_config_destroy(cfg);
   ast_mutex_unlock(&permsconfiglock);
   return 0;
}
int ast_cli_register ( struct ast_cli_entry e)

Registers a command or an array of commands.

Parameters:
ewhich cli entry to register. Register your own command
Return values:
0on success
-1on failure

Definition at line 2109 of file cli.c.

References __ast_cli_register().

Referenced by load_module(), do_reload(), ast_cdr_engine_init(), ast_cel_engine_init(), ast_cli_register_multiple(), dnsmgr_init(), and load_config().

{
   return __ast_cli_register(e, NULL);
}
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 2103 of file cli.c.

References __ast_cli_unregister().

Referenced by unload_module(), do_reload(), load_module(), ast_cli_unregister_multiple(), and alias_destroy().

{
   return __ast_cli_unregister(e, NULL);
}
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 2127 of file cli.c.

References len(), and ast_cli_unregister().

Referenced by unload_module(), load_module(), __unload_module(), ast_ais_clm_unload_module(), and iax_provision_unload().

{
   int i, res = 0;

   for (i = 0; i < len; i++)
      res |= ast_cli_unregister(e + i);

   return res;
}
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 1530 of file cli.c.

References ast_strlen_zero(), ast_channel_iterator_all_new(), ast_channel_iterator_by_name_new(), ast_channel_iterator_next(), ast_channel_lock, ast_strdup, ast_channel::name, ast_channel_unlock, ast_channel_unref, and ast_channel_iterator_destroy().

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

{
   struct ast_channel *c = NULL;
   int which = 0;
   char notfound = '\0';
   char *ret = &notfound; /* so NULL can break the loop */
   struct ast_channel_iterator *iter;

   if (pos != rpos) {
      return NULL;
   }

   if (ast_strlen_zero(word)) {
      iter = ast_channel_iterator_all_new();
   } else {
      iter = ast_channel_iterator_by_name_new(word, strlen(word));
   }

   if (!iter) {
      return NULL;
   }

   while (ret == &notfound && (c = ast_channel_iterator_next(iter))) {
      if (++which > state) {
         ast_channel_lock(c);
         ret = ast_strdup(c->name);
         ast_channel_unlock(c);
      }
      ast_channel_unref(c);
   }

   ast_channel_iterator_destroy(iter);

   return ret == &notfound ? NULL : ret;
}
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 120 of file cli.c.

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

{
   struct module_level *ml;
   unsigned int res = 0;

   AST_RWLIST_RDLOCK(&debug_modules);
   AST_LIST_TRAVERSE(&debug_modules, ml, entry) {
      if (!strcasecmp(ml->module, module)) {
         res = ml->level;
         break;
      }
   }
   AST_RWLIST_UNLOCK(&debug_modules);

   return res;
}
unsigned int ast_verbose_get_by_module ( const char *  module)

Get the verbose level for a module.

Parameters:
modulethe name of module
Returns:
the verbose level

Definition at line 137 of file cli.c.

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

{
   struct module_level *ml;
   unsigned int res = 0;

   AST_RWLIST_RDLOCK(&verbose_modules);
   AST_LIST_TRAVERSE(&verbose_modules, ml, entry) {
      if (!strcasecmp(ml->module, module)) {
         res = ml->level;
         break;
      }
   }
   AST_RWLIST_UNLOCK(&verbose_modules);

   return res;
}
static int channel_set_debug ( void *  obj,
void *  arg,
void *  data,
int  flags 
) [static]

Definition at line 1277 of file cli.c.

References args, ast_channel_lock, ast_channel::fin, DEBUGCHAN_FLAG, ast_channel::fout, channel_set_debug_args::is_off, ast_cli(), channel_set_debug_args::fd, ast_channel::name, and ast_channel_unlock.

Referenced by handle_core_set_debug_channel().

{
   struct ast_channel *chan = obj;
   struct channel_set_debug_args *args = data;

   ast_channel_lock(chan);

   if (!(chan->fin & DEBUGCHAN_FLAG) || !(chan->fout & DEBUGCHAN_FLAG)) {
      if (args->is_off) {
         chan->fin &= ~DEBUGCHAN_FLAG;
         chan->fout &= ~DEBUGCHAN_FLAG;
      } else {
         chan->fin |= DEBUGCHAN_FLAG;
         chan->fout |= DEBUGCHAN_FLAG;
      }
      ast_cli(args->fd, "Debugging %s on channel %s\n", args->is_off ? "disabled" : "enabled",
            chan->name);
   }

   ast_channel_unlock(chan);

   return 0;
}
static int cli_has_permissions ( int  uid,
int  gid,
const char *  command 
) [static]

Definition at line 167 of file cli.c.

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

Referenced by handle_cli_check_permissions(), and ast_cli_command_full().

{
   struct usergroup_cli_perm *user_perm;
   struct cli_perm *perm;
   /* set to the default permissions general option. */
   int isallowg = cli_default_perm, isallowu = -1, ispattern;
   regex_t regexbuf;

   /* if uid == -1 or gid == -1 do not check permissions.
      if uid == -2 and gid == -2 is because rasterisk client didn't send
      the credentials, so the cli_default_perm will be applied. */
   if ((uid == CLI_NO_PERMS && gid == CLI_NO_PERMS) || command[0] == '_') {
      return 1;
   }

   if (gid < 0 && uid < 0) {
      return cli_default_perm;
   }

   AST_RWLIST_RDLOCK(&cli_perms);
   AST_LIST_TRAVERSE(&cli_perms, user_perm, list) {
      if (user_perm->gid != gid && user_perm->uid != uid) {
         continue;
      }
      AST_LIST_TRAVERSE(user_perm->perms, perm, list) {
         if (strcasecmp(perm->command, "all") && strncasecmp(perm->command, command, strlen(perm->command))) {
            /* if the perm->command is a pattern, check it against command. */
            ispattern = !regcomp(&regexbuf, perm->command, REG_EXTENDED | REG_NOSUB | REG_ICASE);
            if (ispattern && regexec(&regexbuf, command, 0, NULL, 0)) {
               regfree(&regexbuf);
               continue;
            }
            if (!ispattern) {
               continue;
            }
            regfree(&regexbuf);
         }
         if (user_perm->uid == uid) {
            /* this is a user definition. */
            isallowu = perm->permit;
         } else {
            /* otherwise is a group definition. */
            isallowg = perm->permit;
         }
      }
   }
   AST_RWLIST_UNLOCK(&cli_perms);
   if (isallowu > -1) {
      /* user definition override group definition. */
      isallowg = isallowu;
   }

   return isallowg;
}
static struct ast_cli_entry* cli_next ( struct ast_cli_entry e) [static, read]

Definition at line 709 of file cli.c.

References AST_LIST_NEXT, and AST_LIST_FIRST.

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

{
   if (e) {
      return AST_LIST_NEXT(e, list);
   } else {
      return AST_LIST_FIRST(&helpers);
   }
}
static char* complete_fn ( const char *  word,
int  state 
) [static]

Definition at line 224 of file cli.c.

References ast_copy_string(), ast_config_AST_MODULE_DIR, ast_strdup, and free.

Referenced by handle_load().

{
   char *c, *d;
   char filename[PATH_MAX];

   if (word[0] == '/')
      ast_copy_string(filename, word, sizeof(filename));
   else
      snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);

   c = d = filename_completion_function(filename, state);
   
   if (c && word[0] != '/')
      c += (strlen(ast_config_AST_MODULE_DIR) + 1);
   if (c)
      c = ast_strdup(c);

   free(d);
   
   return c;
}
static char* complete_number ( const char *  partial,
unsigned int  min,
unsigned int  max,
int  n 
) [static]

Definition at line 346 of file cli.c.

References cli_perm::next, ast_strlen_zero(), and ast_strdup.

Referenced by handle_verbose().

{
   int i, count = 0;
   unsigned int prospective[2];
   unsigned int part = strtoul(partial, NULL, 10);
   char next[12];

   if (part < min || part > max) {
      return NULL;
   }

   for (i = 0; i < 21; i++) {
      if (i == 0) {
         prospective[0] = prospective[1] = part;
      } else if (part == 0 && !ast_strlen_zero(partial)) {
         break;
      } else if (i < 11) {
         prospective[0] = prospective[1] = part * 10 + (i - 1);
      } else {
         prospective[0] = (part * 10 + (i - 11)) * 10;
         prospective[1] = prospective[0] + 9;
      }
      if (i < 11 && (prospective[0] < min || prospective[0] > max)) {
         continue;
      } else if (prospective[1] < min || prospective[0] > max) {
         continue;
      }

      if (++count > n) {
         if (i < 11) {
            snprintf(next, sizeof(next), "%u", prospective[0]);
         } else {
            snprintf(next, sizeof(next), "%u...", prospective[0] / 10);
         }
         return ast_strdup(next);
      }
   }
   return NULL;
}
static void destroy_user_perms ( void  ) [static]

cleanup (free) cli_perms linkedlist.

Definition at line 1719 of file cli.c.

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

Referenced by ast_cli_perms_init().

{
   struct cli_perm *perm;
   struct usergroup_cli_perm *user_perm;

   AST_RWLIST_WRLOCK(&cli_perms);
   while ((user_perm = AST_LIST_REMOVE_HEAD(&cli_perms, list))) {
      while ((perm = AST_LIST_REMOVE_HEAD(user_perm->perms, list))) {
         ast_free(perm->command);
         ast_free(perm);
      }
      ast_free(user_perm);
   }
   AST_RWLIST_UNLOCK(&cli_perms);
}
static char* find_best ( const char *  argv[]) [static]

Definition at line 2007 of file cli.c.

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

Referenced by ast_cli_command_full().

{
   static char cmdline[80];
   int x;
   /* See how close we get, then print the candidate */
   const char *myargv[AST_MAX_CMD_LEN] = { NULL, };

   AST_RWLIST_RDLOCK(&helpers);
   for (x = 0; argv[x]; x++) {
      myargv[x] = argv[x];
      if (!find_cli(myargv, -1))
         break;
   }
   AST_RWLIST_UNLOCK(&helpers);
   ast_join(cmdline, sizeof(cmdline), myargv);
   return cmdline;
}
static struct ast_cli_entry* find_cli ( const char *const  cmds[],
int  match_type 
) [static, read]

Definition at line 1963 of file cli.c.

References cli_next(), ast_cli_entry::cmda, word_match(), and ast_strlen_zero().

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

{
   int matchlen = -1;   /* length of longest match so far */
   struct ast_cli_entry *cand = NULL, *e=NULL;

   while ( (e = cli_next(e)) ) {
      /* word-by word regexp comparison */
      const char * const *src = cmds;
      const char * const *dst = e->cmda;
      int n = 0;
      for (;; dst++, src += n) {
         n = word_match(*src, *dst);
         if (n < 0)
            break;
      }
      if (ast_strlen_zero(*dst) || ((*dst)[0] == '[' && ast_strlen_zero(dst[1]))) {
         /* no more words in 'e' */
         if (ast_strlen_zero(*src)) /* exact match, cannot do better */
            break;
         /* Here, cmds has more words than the entry 'e' */
         if (match_type != 0) /* but we look for almost exact match... */
            continue;   /* so we skip this one. */
         /* otherwise we like it (case 0) */
      } else { /* still words in 'e' */
         if (ast_strlen_zero(*src))
            continue; /* cmds is shorter than 'e', not good */
         /* Here we have leftover words in cmds and 'e',
          * but there is a mismatch. We only accept this one if match_type == -1
          * and this is the last word for both.
          */
         if (match_type != -1 || !ast_strlen_zero(src[1]) ||
             !ast_strlen_zero(dst[1])) /* not the one we look for */
            continue;
         /* good, we are in case match_type == -1 and mismatch on last word */
      }
      if (src - cmds > matchlen) {  /* remember the candidate */
         matchlen = src - cmds;
         cand = e;
      }
   }

   return e ? e : cand;
}
static struct module_level* find_module_level ( const char *  module,
unsigned int  debug 
) [static, read]

Find the debug or verbose file setting.

  • debug 1 for debug, 0 for verbose

Definition at line 333 of file cli.c.

References verbose_modules, and AST_LIST_TRAVERSE.

Referenced by handle_verbose().

{
   struct module_level *ml;
   struct module_level_list *mll = debug ? &debug_modules : &verbose_modules;

   AST_LIST_TRAVERSE(mll, ml, entry) {
      if (!strcasecmp(ml->module, module))
         return ml;
   }

   return NULL;
}
static char* group_show_channels ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1566 of file cli.c.

References CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::argc, CLI_SHOWUSAGE, ast_cli_args::argv, ast_cli(), ast_cli_args::fd, FORMAT_STRING, ast_app_group_list_rdlock(), ast_app_group_list_head(), ast_group_info::group, ast_group_info::chan, ast_channel::name, ast_strlen_zero(), ast_group_info::category, AST_LIST_NEXT, ast_group_info::group_list, ast_app_group_list_unlock(), ESS, and CLI_SUCCESS.

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

   struct ast_group_info *gi = NULL;
   int numchans = 0;
   regex_t regexbuf;
   int havepattern = 0;

   switch (cmd) {
   case CLI_INIT:
      e->command = "group show channels";
      e->usage = 
         "Usage: group show channels [pattern]\n"
         "       Lists all currently active channels with channel group(s) specified.\n"
         "       Optional regular expression pattern is matched to group names for each\n"
         "       channel.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   if (a->argc < 3 || a->argc > 4)
      return CLI_SHOWUSAGE;
   
   if (a->argc == 4) {
      if (regcomp(&regexbuf, a->argv[3], REG_EXTENDED | REG_NOSUB))
         return CLI_SHOWUSAGE;
      havepattern = 1;
   }

   ast_cli(a->fd, FORMAT_STRING, "Channel", "Group", "Category");

   ast_app_group_list_rdlock();
   
   gi = ast_app_group_list_head();
   while (gi) {
      if (!havepattern || !regexec(&regexbuf, gi->group, 0, NULL, 0)) {
         ast_cli(a->fd, FORMAT_STRING, gi->chan->name, gi->group, (ast_strlen_zero(gi->category) ? "(default)" : gi->category));
         numchans++;
      }
      gi = AST_LIST_NEXT(gi, group_list);
   }
   
   ast_app_group_list_unlock();
   
   if (havepattern)
      regfree(&regexbuf);

   ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
   return CLI_SUCCESS;
#undef FORMAT_STRING
}
static char* handle_chanlist ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 843 of file cli.c.

References CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, CLI_SHOWUSAGE, ast_cli(), ast_cli_args::fd, FORMAT_STRING2, VERBOSE_FORMAT_STRING2, ast_channel_iterator_all_new(), CLI_FAILURE, ast_channel_iterator_next(), ast_channel_unref, ast_channel_lock, ast_bridged_channel(), ast_tvzero(), ast_tvdiff_ms(), ast_tvnow(), CONCISE_FORMAT_STRING, ast_state2str(), S_OR, S_COR, ast_channel::name, VERBOSE_FORMAT_STRING, ast_strlen_zero(), FORMAT_STRING, ast_channel_unlock, ast_channel_iterator_destroy(), ast_active_channels(), ESS, option_maxcalls, ast_active_calls(), ast_processed_calls(), and CLI_SUCCESS.

{
#define FORMAT_STRING  "%-20.20s %-20.20s %-7.7s %-30.30s\n"
#define FORMAT_STRING2 "%-20.20s %-20.20s %-7.7s %-30.30s\n"
#define CONCISE_FORMAT_STRING  "%s!%s!%s!%d!%s!%s!%s!%s!%s!%s!%d!%s!%s!%s\n"
#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"

   struct ast_channel *c = NULL;
   int numchans = 0, concise = 0, verbose = 0, count = 0;
   struct ast_channel_iterator *iter = NULL;

   switch (cmd) {
   case CLI_INIT:
      e->command = "core show channels [concise|verbose|count]";
      e->usage =
         "Usage: core show channels [concise|verbose|count]\n"
         "       Lists currently defined channels and some information about them. If\n"
         "       'concise' is specified, the format is abridged and in a more easily\n"
         "       machine parsable format. If 'verbose' is specified, the output includes\n"
         "       more and longer fields. If 'count' is specified only the channel and call\n"
         "       count is output.\n"
         "  The 'concise' option is deprecated and will be removed from future versions\n"
         "  of Asterisk.\n";
      return NULL;

   case CLI_GENERATE:
      return NULL;
   }

   if (a->argc == e->args) {
      if (!strcasecmp(a->argv[e->args-1],"concise"))
         concise = 1;
      else if (!strcasecmp(a->argv[e->args-1],"verbose"))
         verbose = 1;
      else if (!strcasecmp(a->argv[e->args-1],"count"))
         count = 1;
      else
         return CLI_SHOWUSAGE;
   } else if (a->argc != e->args - 1)
      return CLI_SHOWUSAGE;

   if (!count) {
      if (!concise && !verbose)
         ast_cli(a->fd, FORMAT_STRING2, "Channel", "Location", "State", "Application(Data)");
      else if (verbose)
         ast_cli(a->fd, VERBOSE_FORMAT_STRING2, "Channel", "Context", "Extension", "Priority", "State", "Application", "Data", 
            "CallerID", "Duration", "Accountcode", "PeerAccount", "BridgedTo");
   }

   if (!count && !(iter = ast_channel_iterator_all_new())) {
      return CLI_FAILURE;
   }

   for (; iter && (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
      struct ast_channel *bc;
      char durbuf[10] = "-";

      ast_channel_lock(c);

      bc = ast_bridged_channel(c);

      if (!count) {
         if ((concise || verbose)  && c->cdr && !ast_tvzero(c->cdr->start)) {
            int duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
            if (verbose) {
               int durh = duration / 3600;
               int durm = (duration % 3600) / 60;
               int durs = duration % 60;
               snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
            } else {
               snprintf(durbuf, sizeof(durbuf), "%d", duration);
            }           
         }
         if (concise) {
            ast_cli(a->fd, CONCISE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
               c->appl ? c->appl : "(None)",
               S_OR(c->data, ""),   /* XXX different from verbose ? */
               S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""),
               S_OR(c->accountcode, ""),
               S_OR(c->peeraccount, ""),
               c->amaflags, 
               durbuf,
               bc ? bc->name : "(None)",
               c->uniqueid);
         } else if (verbose) {
            ast_cli(a->fd, VERBOSE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
               c->appl ? c->appl : "(None)",
               c->data ? S_OR(c->data, "(Empty)" ): "(None)",
               S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""),
               durbuf,
               S_OR(c->accountcode, ""),
               S_OR(c->peeraccount, ""),
               bc ? bc->name : "(None)");
         } else {
            char locbuf[40] = "(None)";
            char appdata[40] = "(None)";
            
            if (!ast_strlen_zero(c->context) && !ast_strlen_zero(c->exten)) 
               snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", c->exten, c->context, c->priority);
            if (c->appl)
               snprintf(appdata, sizeof(appdata), "%s(%s)", c->appl, S_OR(c->data, ""));
            ast_cli(a->fd, FORMAT_STRING, c->name, locbuf, ast_state2str(c->_state), appdata);
         }
      }
      ast_channel_unlock(c);
   }

   if (iter) {
      ast_channel_iterator_destroy(iter);
   }

   if (!concise) {
      numchans = ast_active_channels();
      ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
      if (option_maxcalls)
         ast_cli(a->fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
            ast_active_calls(), option_maxcalls, ESS(ast_active_calls()),
            ((double)ast_active_calls() / (double)option_maxcalls) * 100.0);
      else
         ast_cli(a->fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));

      ast_cli(a->fd, "%d call%s processed\n", ast_processed_calls(), ESS(ast_processed_calls()));
   }

   return CLI_SUCCESS;
   
#undef FORMAT_STRING
#undef FORMAT_STRING2
#undef CONCISE_FORMAT_STRING
#undef VERBOSE_FORMAT_STRING
#undef VERBOSE_FORMAT_STRING2
}
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 1089 of file cli.c.

References cli_perm::command, AST_MAX_ARGS, group, CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::pos, ast_cli_generator(), ast_cli_args::line, ast_cli_args::argv, ast_cli_args::word, ast_cli_args::n, ast_cli_args::argc, CLI_SHOWUSAGE, ast_strdupa, ast_cli(), ast_cli_args::fd, CLI_FAILURE, ast_strlen_zero(), cli_next(), ast_cli_entry::_full_cmd, cli_has_permissions(), S_OR, ast_cli_entry::summary, ast_join(), and CLI_SUCCESS.

{
   struct passwd *pw = NULL;
   struct group *gr;
   int gid = -1, uid = -1;
   char command[AST_MAX_ARGS] = "";
   struct ast_cli_entry *ce = NULL;
   int found = 0;
   char *group, *tmp;

   switch (cmd) {
   case CLI_INIT:
      e->command = "cli check permissions";
      e->usage =
         "Usage: cli check permissions {<username>|@<groupname>|<username>@<groupname>} [<command>]\n"
         "       Check permissions config for a user@group or list the allowed commands for the specified user.\n"
         "       The username or the groupname may be omitted.\n";
      return NULL;
   case CLI_GENERATE:
      if (a->pos >= 4) {
         return ast_cli_generator(a->line + strlen("cli check permissions") + strlen(a->argv[3]) + 1, a->word, a->n);
      }
      return NULL;
   }

   if (a->argc < 4) {
      return CLI_SHOWUSAGE;
   }

   tmp = ast_strdupa(a->argv[3]);
   group = strchr(tmp, '@');
   if (group) {
      gr = getgrnam(&group[1]);
      if (!gr) {
         ast_cli(a->fd, "Unknown group '%s'\n", &group[1]);
         return CLI_FAILURE;
      }
      group[0] = '\0';
      gid = gr->gr_gid;
   }

   if (!group && ast_strlen_zero(tmp)) {
      ast_cli(a->fd, "You didn't supply a username\n");
   } else if (!ast_strlen_zero(tmp) && !(pw = getpwnam(tmp))) {
      ast_cli(a->fd, "Unknown user '%s'\n", tmp);
      return CLI_FAILURE;
   } else if (pw) {
      uid = pw->pw_uid;
   }

   if (a->argc == 4) {
      while ((ce = cli_next(ce))) {
         /* Hide commands that start with '_' */
         if (ce->_full_cmd[0] == '_') {
            continue;
         }
         if (cli_has_permissions(uid, gid, ce->_full_cmd)) {
            ast_cli(a->fd, "%30.30s %s\n", ce->_full_cmd, S_OR(ce->summary, "<no description available>"));
            found++;
         }
      }
      if (!found) {
         ast_cli(a->fd, "You are not allowed to run any command on Asterisk\n");
      }
   } else {
      ast_join(command, sizeof(command), a->argv + 4);
      ast_cli(a->fd, "%s '%s%s%s' is %s to run command: '%s'\n", uid >= 0 ? "User" : "Group", tmp,
         group && uid >= 0 ? "@" : "",
         group ? &group[1] : "",
         cli_has_permissions(uid, gid, command) ? "allowed" : "not allowed", command);
   }

   return CLI_SUCCESS;
}
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 1070 of file cli.c.

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

{
   switch (cmd) {
   case CLI_INIT:
      e->command = "cli reload permissions";
      e->usage =
         "Usage: cli reload permissions\n"
         "       Reload the 'cli_permissions.conf' file.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   ast_cli_perms_init(1);

   return CLI_SUCCESS;
}
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 1025 of file cli.c.

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

{
   struct usergroup_cli_perm *cp;
   struct cli_perm *perm;
   struct passwd *pw = NULL;
   struct group *gr = NULL;

   switch (cmd) {
   case CLI_INIT:
      e->command = "cli show permissions";
      e->usage =
         "Usage: cli show permissions\n"
         "       Shows CLI configured permissions.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   AST_RWLIST_RDLOCK(&cli_perms);
   AST_LIST_TRAVERSE(&cli_perms, cp, list) {
      if (cp->uid >= 0) {
         pw = getpwuid(cp->uid);
         if (pw) {
            ast_cli(a->fd, "user: %s [uid=%d]\n", pw->pw_name, cp->uid);
         }
      } else {
         gr = getgrgid(cp->gid);
         if (gr) {
            ast_cli(a->fd, "group: %s [gid=%d]\n", gr->gr_name, cp->gid);
         }
      }
      ast_cli(a->fd, "Permissions:\n");
      if (cp->perms) {
         AST_LIST_TRAVERSE(cp->perms, perm, list) {
            ast_cli(a->fd, "\t%s -> %s\n", perm->permit ? "permit" : "deny", perm->command);
         }
      }
      ast_cli(a->fd, "\n");
   }
   AST_RWLIST_UNLOCK(&cli_perms);

   return CLI_SUCCESS;
}
static char* handle_cli_wait_fullybooted ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1620 of file cli.c.

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

{
   switch (cmd) {
   case CLI_INIT:
      e->command = "core waitfullybooted";
      e->usage =
         "Usage: core waitfullybooted\n"
         "  Wait until Asterisk has fully booted.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   while (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
      usleep(100);
   }

   ast_cli(a->fd, "Asterisk has fully booted.\n");

   return CLI_SUCCESS;
}
static char* handle_commandcomplete ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1247 of file cli.c.

References CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::argc, CLI_SHOWUSAGE, __ast_cli_generator(), ast_cli_args::argv, ast_cli(), ast_cli_args::fd, ast_free, and CLI_SUCCESS.

{
   char *buf;
   switch (cmd) {
   case CLI_INIT:
      e->command = "_command complete";
      e->usage = 
         "Usage: _command complete \"<line>\" text state\n"
         "       This function is used internally to help with command completion and should.\n"
         "       never be called by the user directly.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }
   if (a->argc != 5)
      return CLI_SHOWUSAGE;
   buf = __ast_cli_generator(a->argv[2], a->argv[3], atoi(a->argv[4]), 0);
   if (buf) {
      ast_cli(a->fd, "%s", buf);
      ast_free(buf);
   } else
      ast_cli(a->fd, "NULL\n");
   return CLI_SUCCESS;
}
static char* handle_commandmatchesarray ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1166 of file cli.c.

References len(), CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::argc, CLI_SHOWUSAGE, ast_malloc, CLI_FAILURE, ast_cli_completion_matches(), ast_cli_args::argv, ast_realloc, ast_free, ast_cli(), ast_cli_args::fd, AST_CLI_COMPLETE_EOF, and CLI_SUCCESS.

{
   char *buf, *obuf;
   int buflen = 2048;
   int len = 0;
   char **matches;
   int x, matchlen;
   
   switch (cmd) {
   case CLI_INIT:
      e->command = "_command matchesarray";
      e->usage = 
         "Usage: _command matchesarray \"<line>\" text \n"
         "       This function is used internally to help with command completion and should.\n"
         "       never be called by the user directly.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   if (a->argc != 4)
      return CLI_SHOWUSAGE;
   if (!(buf = ast_malloc(buflen)))
      return CLI_FAILURE;
   buf[len] = '\0';
   matches = ast_cli_completion_matches(a->argv[2], a->argv[3]);
   if (matches) {
      for (x=0; matches[x]; x++) {
         matchlen = strlen(matches[x]) + 1;
         if (len + matchlen >= buflen) {
            buflen += matchlen * 3;
            obuf = buf;
            if (!(buf = ast_realloc(obuf, buflen))) 
               /* Memory allocation failure...  Just free old buffer and be done */
               ast_free(obuf);
         }
         if (buf)
            len += sprintf( buf + len, "%s ", matches[x]);
         ast_free(matches[x]);
         matches[x] = NULL;
      }
      ast_free(matches);
   }

   if (buf) {
      ast_cli(a->fd, "%s%s",buf, AST_CLI_COMPLETE_EOF);
      ast_free(buf);
   } else
      ast_cli(a->fd, "NULL\n");

   return CLI_SUCCESS;
}
static char* handle_commandnummatches ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1221 of file cli.c.

References CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::argc, CLI_SHOWUSAGE, ast_cli_generatornummatches(), ast_cli_args::argv, ast_cli(), ast_cli_args::fd, and CLI_SUCCESS.

{
   int matches = 0;

   switch (cmd) {
   case CLI_INIT:
      e->command = "_command nummatches";
      e->usage = 
         "Usage: _command nummatches \"<line>\" text \n"
         "       This function is used internally to help with command completion and should.\n"
         "       never be called by the user directly.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   if (a->argc != 4)
      return CLI_SHOWUSAGE;

   matches = ast_cli_generatornummatches(a->argv[2], a->argv[3]);

   ast_cli(a->fd, "%d", matches);

   return CLI_SUCCESS;
}
static char* handle_core_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 307 of file cli.c.

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

{
   switch (cmd) {
   case CLI_INIT:
      e->command = "core reload";
      e->usage =
         "Usage: core reload\n"
         "       Execute a global reload.\n";
      return NULL;

   case CLI_GENERATE:
      return NULL;
   }

   if (a->argc != e->args) {
      return CLI_SHOWUSAGE;
   }

   ast_module_reload(NULL);

   return CLI_SUCCESS;
}
static char* handle_core_set_debug_channel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1301 of file cli.c.

References channel_set_debug_args::fd, ast_cli_args::fd, CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::pos, ast_cli_entry::args, ast_cli_args::n, ast_strdup, ast_complete_channels(), ast_cli_args::line, ast_cli_args::word, CLI_HANDLER, channel_set_debug_args::is_off, ast_cli_args::argc, ast_cli_args::argv, CLI_SHOWUSAGE, global_fin, DEBUGCHAN_FLAG, global_fout, ast_channel_callback(), channel_set_debug(), OBJ_NODATA, OBJ_MULTIPLE, ast_channel_get_by_name(), ast_channel_unref, ast_cli(), and CLI_SUCCESS.

Referenced by handle_nodebugchan_deprecated().

{
   struct ast_channel *c = NULL;
   struct channel_set_debug_args args = {
      .fd = a->fd,
   };

   switch (cmd) {
   case CLI_INIT:
      e->command = "core set debug channel";
      e->usage =
         "Usage: core set debug channel <all|channel> [off]\n"
         "       Enables/disables debugging on all or on a specific channel.\n";
      return NULL;
   case CLI_GENERATE:
      /* XXX remember to handle the optional "off" */
      if (a->pos != e->args)
         return NULL;
      return a->n == 0 ? ast_strdup("all") : ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
   }

   if (cmd == (CLI_HANDLER + 1000)) {
      /* called from handle_nodebugchan_deprecated */
      args.is_off = 1;
   } else if (a->argc == e->args + 2) {
      /* 'core set debug channel {all|chan_id}' */
      if (!strcasecmp(a->argv[e->args + 1], "off"))
         args.is_off = 1;
      else
         return CLI_SHOWUSAGE;
   } else if (a->argc != e->args + 1) {
      return CLI_SHOWUSAGE;
   }

   if (!strcasecmp("all", a->argv[e->args])) {
      if (args.is_off) {
         global_fin &= ~DEBUGCHAN_FLAG;
         global_fout &= ~DEBUGCHAN_FLAG;
      } else {
         global_fin |= DEBUGCHAN_FLAG;
         global_fout |= DEBUGCHAN_FLAG;
      }
      ast_channel_callback(channel_set_debug, NULL, &args, OBJ_NODATA | OBJ_MULTIPLE);
   } else {
      if ((c = ast_channel_get_by_name(a->argv[e->args]))) {
         channel_set_debug(c, NULL, &args, 0);
         ast_channel_unref(c);
      } else {
         ast_cli(a->fd, "No such channel %s\n", a->argv[e->args]);
      }
   }

   ast_cli(a->fd, "Debugging on new channels is %s\n", args.is_off ? "disabled" : "enabled");

   return CLI_SUCCESS;
}
static char * handle_help ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2170 of file cli.c.

References CLI_SUCCESS, CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::line, __ast_cli_generator(), ast_cli_args::word, ast_cli_args::n, ast_cli_args::argc, ast_cli_entry::args, help1(), ast_cli_args::fd, AST_RWLIST_RDLOCK, find_cli(), ast_cli_args::argv, AST_RWLIST_UNLOCK, ast_cli(), and ast_join().

{
   char fullcmd[80];
   struct ast_cli_entry *my_e;
   char *res = CLI_SUCCESS;

   if (cmd == CLI_INIT) {
      e->command = "core show help";
      e->usage =
         "Usage: core show help [topic]\n"
         "       When called with a topic as an argument, displays usage\n"
         "       information on the given command. If called without a\n"
         "       topic, it provides a list of commands.\n";
      return NULL;

   } else if (cmd == CLI_GENERATE) {
      /* skip first 14 or 15 chars, "core show help " */
      int l = strlen(a->line);

      if (l > 15) {
         l = 15;
      }
      /* XXX watch out, should stop to the non-generator parts */
      return __ast_cli_generator(a->line + l, a->word, a->n, 0);
   }
   if (a->argc == e->args) {
      return help1(a->fd, NULL, 0);
   }

   AST_RWLIST_RDLOCK(&helpers);
   my_e = find_cli(a->argv + 3, 1); /* try exact match first */
   if (!my_e) {
      res = help1(a->fd, a->argv + 3, 1 /* locked */);
      AST_RWLIST_UNLOCK(&helpers);
      return res;
   }
   if (my_e->usage)
      ast_cli(a->fd, "%s", my_e->usage);
   else {
      ast_join(fullcmd, sizeof(fullcmd), a->argv + 3);
      ast_cli(a->fd, "No help text available for '%s'.\n", fullcmd);
   }
   AST_RWLIST_UNLOCK(&helpers);
   return res;
}
static char* handle_load ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 246 of file cli.c.

References CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::pos, ast_cli_entry::args, complete_fn(), ast_cli_args::word, ast_cli_args::n, ast_cli_args::argc, CLI_SHOWUSAGE, ast_load_resource(), ast_cli_args::argv, ast_cli(), ast_cli_args::fd, CLI_FAILURE, and CLI_SUCCESS.

{
   /* "module load <mod>" */
   switch (cmd) {
   case CLI_INIT:
      e->command = "module load";
      e->usage =
         "Usage: module load <module name>\n"
         "       Loads the specified module into Asterisk.\n";
      return NULL;

   case CLI_GENERATE:
      if (a->pos != e->args)
         return NULL;
      return complete_fn(a->word, a->n);
   }
   if (a->argc != e->args + 1)
      return CLI_SHOWUSAGE;
   if (ast_load_resource(a->argv[e->args])) {
      ast_cli(a->fd, "Unable to load module %s\n", a->argv[e->args]);
      return CLI_FAILURE;
   }
   ast_cli(a->fd, "Loaded %s\n", a->argv[e->args]);
   return CLI_SUCCESS;
}
static char* handle_logger_mute ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 568 of file cli.c.

References CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::argc, CLI_SHOWUSAGE, ast_cli_args::argv, ast_console_toggle_mute(), ast_cli_args::fd, and CLI_SUCCESS.

{
   switch (cmd) {
   case CLI_INIT:
      e->command = "logger mute";
      e->usage = 
         "Usage: logger mute\n"
         "       Disables logging output to the current console, making it possible to\n"
         "       gather information without being disturbed by scrolling lines.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   if (a->argc < 2 || a->argc > 3)
      return CLI_SHOWUSAGE;

   if (a->argc == 3 && !strcasecmp(a->argv[2], "silent"))
      ast_console_toggle_mute(a->fd, 1);
   else
      ast_console_toggle_mute(a->fd, 0);

   return CLI_SUCCESS;
}
static char* handle_modlist ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 749 of file cli.c.

References CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::pos, ast_cli_entry::args, ast_module_helper(), ast_cli_args::line, ast_cli_args::word, ast_cli_args::n, ast_cli_args::argc, ast_cli_args::argv, CLI_SHOWUSAGE, ast_mutex_lock, climodentrylock, ast_cli_args::fd, ast_cli(), MODLIST_FORMAT2, ast_update_module_list(), modlist_modentry(), ast_mutex_unlock, and CLI_SUCCESS.

{
   const char *like;

   switch (cmd) {
   case CLI_INIT:
      e->command = "module show [like]";
      e->usage =
         "Usage: module show [like keyword]\n"
         "       Shows Asterisk modules currently in use, and usage statistics.\n";
      return NULL;

   case CLI_GENERATE:
      if (a->pos == e->args)
         return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);
      else
         return NULL;
   }
   /* all the above return, so we proceed with the handler.
    * we are guaranteed to have argc >= e->args
    */
   if (a->argc == e->args - 1)
      like = "";
   else if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args-1], "like") )
      like = a->argv[e->args];
   else
      return CLI_SHOWUSAGE;
      
   ast_mutex_lock(&climodentrylock);
   climodentryfd = a->fd; /* global, protected by climodentrylock */
   ast_cli(a->fd, MODLIST_FORMAT2, "Module", "Description", "Use Count");
   ast_cli(a->fd,"%d modules loaded\n", ast_update_module_list(modlist_modentry, like));
   climodentryfd = -1;
   ast_mutex_unlock(&climodentrylock);
   return CLI_SUCCESS;
}
static char* handle_nodebugchan_deprecated ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1358 of file cli.c.

References CLI_INIT, ast_cli_entry::command, CLI_HANDLER, ast_cli_args::argc, ast_cli_entry::args, CLI_SHOWUSAGE, and handle_core_set_debug_channel().

{
   char *res;

   switch (cmd) {
   case CLI_INIT:
      e->command = "no debug channel";
      return NULL;
   case CLI_HANDLER:
      /* exit out of switch statement */
      break;
   default:
      return NULL;
   }

   if (a->argc != e->args + 1)
      return CLI_SHOWUSAGE;

   /* add a 'magic' value to the CLI_HANDLER command so that
    * handle_core_set_debug_channel() will act as if 'off'
    * had been specified as part of the command
    */
   res = handle_core_set_debug_channel(e, CLI_HANDLER + 1000, a);

   return res;
}
static char* handle_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 272 of file cli.c.

References CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_module_helper(), ast_cli_args::line, ast_cli_args::word, ast_cli_args::pos, ast_cli_args::n, ast_cli_args::argc, ast_cli_entry::args, ast_module_reload(), CLI_SUCCESS, ast_cli_args::argv, ast_cli(), and ast_cli_args::fd.

{
   int x;

   switch (cmd) {
   case CLI_INIT:
      e->command = "module reload";
      e->usage =
         "Usage: module reload [module ...]\n"
         "       Reloads configuration files for all listed modules which support\n"
         "       reloading, or for all supported modules if none are listed.\n";
      return NULL;

   case CLI_GENERATE:
      return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 1);
   }
   if (a->argc == e->args) {
      ast_module_reload(NULL);
      return CLI_SUCCESS;
   }
   for (x = e->args; x < a->argc; x++) {
      int res = ast_module_reload(a->argv[x]);
      /* XXX reload has multiple error returns, including -1 on error and 2 on success */
      switch (res) {
      case 0:
         ast_cli(a->fd, "No such module '%s'\n", a->argv[x]);
         break;
      case 1:
         ast_cli(a->fd, "Module '%s' does not support reload\n", a->argv[x]);
         break;
      }
   }
   return CLI_SUCCESS;
}
static char* handle_showcalls ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 788 of file cli.c.

References ast_tvnow(), CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::pos, ast_cli_entry::args, ast_cli_args::n, ast_strdup, ast_cli_args::argc, ast_cli_args::argv, CLI_SHOWUSAGE, option_maxcalls, ast_cli(), ast_cli_args::fd, ast_active_calls(), ESS, ast_processed_calls(), ast_startuptime, print_uptimestr(), ast_tvsub(), and RESULT_SUCCESS.

{
   struct timeval curtime = ast_tvnow();
   int showuptime, printsec;

   switch (cmd) {
   case CLI_INIT:
      e->command = "core show calls [uptime]";
      e->usage =
         "Usage: core show calls [uptime] [seconds]\n"
         "       Lists number of currently active calls and total number of calls\n"
         "       processed through PBX since last restart. If 'uptime' is specified\n"
         "       the system uptime is also displayed. If 'seconds' is specified in\n"
         "       addition to 'uptime', the system uptime is displayed in seconds.\n";
      return NULL;

   case CLI_GENERATE:
      if (a->pos != e->args)
         return NULL;
      return a->n == 0  ? ast_strdup("seconds") : NULL;
   }

   /* regular handler */
   if (a->argc >= e->args && !strcasecmp(a->argv[e->args-1],"uptime")) {
      showuptime = 1;

      if (a->argc == e->args+1 && !strcasecmp(a->argv[e->args],"seconds"))
         printsec = 1;
      else if (a->argc == e->args)
         printsec = 0;
      else
         return CLI_SHOWUSAGE;
   } else if (a->argc == e->args-1) {
      showuptime = 0;
      printsec = 0;
   } else
      return CLI_SHOWUSAGE;

   if (option_maxcalls) {
      ast_cli(a->fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
         ast_active_calls(), option_maxcalls, ESS(ast_active_calls()),
         ((double)ast_active_calls() / (double)option_maxcalls) * 100.0);
   } else {
      ast_cli(a->fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
   }
   
   ast_cli(a->fd, "%d call%s processed\n", ast_processed_calls(), ESS(ast_processed_calls()));

   if (ast_startuptime.tv_sec && showuptime) {
      print_uptimestr(a->fd, ast_tvsub(curtime, ast_startuptime), "System uptime", printsec);
   }

   return RESULT_SUCCESS;
}
static char* handle_showchan ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1385 of file cli.c.

References ast_str_thread_get(), ast_str_alloca, CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_complete_channels(), ast_cli_args::line, ast_cli_args::word, ast_cli_args::pos, ast_cli_args::n, ast_cli_args::argc, CLI_SHOWUSAGE, ast_tvnow(), ast_channel_get_by_name(), ast_cli_args::argv, ast_cli(), ast_cli_args::fd, CLI_SUCCESS, ast_channel_lock, ast_channel::cdr, ast_cdr::start, ast_channel::name, ast_channel::tech, ast_channel_tech::type, ast_channel::uniqueid, ast_channel::linkedid, S_COR, ast_channel::caller, ast_party_caller::id, ast_party_id::number, ast_party_number::valid, ast_party_number::str, ast_party_id::name, ast_party_name::valid, ast_party_name::str, ast_channel::connected, ast_party_connected_line::id, S_OR, ast_channel::dialed, ast_party_dialed::number, ast_party_dialed::str, ast_channel::language, ast_state2str(), ast_channel::_state, ast_channel::rings, ast_getformatname_multiple(), ast_channel::nativeformats, ast_channel::writeformat, ast_channel::readformat, ast_channel::writetrans, ast_translate_path_to_str(), ast_channel::readtrans, ast_channel::fds, ast_channel::fin, DEBUGCHAN_FLAG, ast_channel::fout, ast_channel::whentohangup, ast_channel::_bridge, ast_bridged_channel(), name, ast_channel::context, ast_channel::exten, ast_channel::priority, ast_channel::callgroup, ast_channel::pickupgroup, ast_channel::appl, ast_channel::data, ast_test_flag, AST_FLAG_BLOCKING, ast_channel::blockproc, pbx_builtin_serialize_variables(), ast_str_buffer(), ast_cdr_serialize_variables(), ast_channel_unlock, and ast_channel_unref.

{
   struct ast_channel *c=NULL;
   struct timeval now;
   struct ast_str *out = ast_str_thread_get(&ast_str_thread_global_buf, 16);
   char cdrtime[256];
   char nf[256], wf[256], rf[256];
   struct ast_str *write_transpath = ast_str_alloca(256);
   struct ast_str *read_transpath = ast_str_alloca(256);
   long elapsed_seconds=0;
   int hour=0, min=0, sec=0;
#ifdef CHANNEL_TRACE
   int trace_enabled;
#endif

   switch (cmd) {
   case CLI_INIT:
      e->command = "core show channel";
      e->usage = 
         "Usage: core show channel <channel>\n"
         "       Shows lots of information about the specified channel.\n";
      return NULL;
   case CLI_GENERATE:
      return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
   }
   
   if (a->argc != 4) {
      return CLI_SHOWUSAGE;
   }

   now = ast_tvnow();

   if (!(c = ast_channel_get_by_name(a->argv[3]))) {
      ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
      return CLI_SUCCESS;
   }

   ast_channel_lock(c);

   if (c->cdr) {
      elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
      hour = elapsed_seconds / 3600;
      min = (elapsed_seconds % 3600) / 60;
      sec = elapsed_seconds % 60;
      snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
   } else {
      strcpy(cdrtime, "N/A");
   }

   ast_cli(a->fd, 
      " -- General --\n"
      "           Name: %s\n"
      "           Type: %s\n"
      "       UniqueID: %s\n"
      "       LinkedID: %s\n"
      "      Caller ID: %s\n"
      " Caller ID Name: %s\n"
      "Connected Line ID: %s\n"
      "Connected Line ID Name: %s\n"
      "    DNID Digits: %s\n"
      "       Language: %s\n"
      "          State: %s (%d)\n"
      "          Rings: %d\n"
      "  NativeFormats: %s\n"
      "    WriteFormat: %s\n"
      "     ReadFormat: %s\n"
      " WriteTranscode: %s %s\n"
      "  ReadTranscode: %s %s\n"
      "1st File Descriptor: %d\n"
      "      Frames in: %d%s\n"
      "     Frames out: %d%s\n"
      " Time to Hangup: %ld\n"
      "   Elapsed Time: %s\n"
      "  Direct Bridge: %s\n"
      "Indirect Bridge: %s\n"
      " --   PBX   --\n"
      "        Context: %s\n"
      "      Extension: %s\n"
      "       Priority: %d\n"
      "     Call Group: %llu\n"
      "   Pickup Group: %llu\n"
      "    Application: %s\n"
      "           Data: %s\n"
      "    Blocking in: %s\n",
      c->name, c->tech->type, c->uniqueid, c->linkedid,
      S_COR(c->caller.id.number.valid, c->caller.id.number.str, "(N/A)"),
      S_COR(c->caller.id.name.valid, c->caller.id.name.str, "(N/A)"),
      S_COR(c->connected.id.number.valid, c->connected.id.number.str, "(N/A)"),
      S_COR(c->connected.id.name.valid, c->connected.id.name.str, "(N/A)"),
      S_OR(c->dialed.number.str, "(N/A)"),
      c->language,   
      ast_state2str(c->_state), c->_state, c->rings, 
      ast_getformatname_multiple(nf, sizeof(nf), c->nativeformats), 
      ast_getformatname_multiple(wf, sizeof(wf), c->writeformat), 
      ast_getformatname_multiple(rf, sizeof(rf), c->readformat),
      c->writetrans ? "Yes" : "No",
      ast_translate_path_to_str(c->writetrans, &write_transpath),
      c->readtrans ? "Yes" : "No",
      ast_translate_path_to_str(c->readtrans, &read_transpath),
      c->fds[0],
      c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
      c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
      (long)c->whentohangup.tv_sec,
      cdrtime, c->_bridge ? c->_bridge->name : "<none>", ast_bridged_channel(c) ? ast_bridged_channel(c)->name : "<none>", 
      c->context, c->exten, c->priority, c->callgroup, c->pickupgroup, ( c->appl ? c->appl : "(N/A)" ),
      ( c-> data ? S_OR(c->data, "(Empty)") : "(None)"),
      (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
   
   if (pbx_builtin_serialize_variables(c, &out)) {
      ast_cli(a->fd,"      Variables:\n%s\n", ast_str_buffer(out));
   }

   if (c->cdr && ast_cdr_serialize_variables(c->cdr, &out, '=', '\n', 1)) {
      ast_cli(a->fd,"  CDR Variables:\n%s\n", ast_str_buffer(out));
   }

#ifdef CHANNEL_TRACE
   trace_enabled = ast_channel_trace_is_enabled(c);
   ast_cli(a->fd, "  Context Trace: %s\n", trace_enabled ? "Enabled" : "Disabled");
   if (trace_enabled && ast_channel_trace_serialize(c, &out))
      ast_cli(a->fd, "          Trace:\n%s\n", ast_str_buffer(out));
#endif

   ast_channel_unlock(c);
   c = ast_channel_unref(c);

   return CLI_SUCCESS;
}
static char* handle_showuptime ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 718 of file cli.c.

References ast_tvnow(), CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, CLI_SHOWUSAGE, ast_startuptime, print_uptimestr(), ast_cli_args::fd, ast_tvsub(), ast_lastreloadtime, and CLI_SUCCESS.

{
   struct timeval curtime = ast_tvnow();
   int printsec;

   switch (cmd) {
   case CLI_INIT:
      e->command = "core show uptime [seconds]";
      e->usage =
         "Usage: core show uptime [seconds]\n"
         "       Shows Asterisk uptime information.\n"
         "       The seconds word returns the uptime in seconds only.\n";
      return NULL;

   case CLI_GENERATE:
      return NULL;
   }
   /* regular handler */
   if (a->argc == e->args && !strcasecmp(a->argv[e->args-1],"seconds"))
      printsec = 1;
   else if (a->argc == e->args-1)
      printsec = 0;
   else
      return CLI_SHOWUSAGE;
   if (ast_startuptime.tv_sec)
      print_uptimestr(a->fd, ast_tvsub(curtime, ast_startuptime), "System uptime", printsec);
   if (ast_lastreloadtime.tv_sec)
      print_uptimestr(a->fd, ast_tvsub(curtime, ast_lastreloadtime), "Last reload", printsec);
   return CLI_SUCCESS;
}
static char* handle_softhangup ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 977 of file cli.c.

References CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_complete_channels(), ast_cli_args::line, ast_cli_args::word, ast_cli_args::pos, ast_cli_args::n, ast_cli_entry::args, ast_cli_args::argc, CLI_SHOWUSAGE, ast_cli_args::argv, ast_channel_iterator_all_new(), CLI_FAILURE, ast_channel_iterator_next(), ast_channel_unref, ast_channel_lock, ast_cli(), ast_cli_args::fd, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_channel_unlock, ast_channel_iterator_destroy(), ast_channel_get_by_name(), ast_channel::name, and CLI_SUCCESS.

{
   struct ast_channel *c=NULL;

   switch (cmd) {
   case CLI_INIT:
      e->command = "channel request hangup";
      e->usage =
         "Usage: channel request hangup <channel>|<all>\n"
         "       Request that a channel be hung up. The hangup takes effect\n"
         "       the next time the driver reads or writes from the channel.\n"
         "       If 'all' is specified instead of a channel name, all channels\n"
         "       will see the hangup request.\n";
      return NULL;
   case CLI_GENERATE:
      return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args);
   }

   if (a->argc != 4) {
      return CLI_SHOWUSAGE;
   }

   if (!strcasecmp(a->argv[3], "all")) {
      struct ast_channel_iterator *iter = NULL;
      if (!(iter = ast_channel_iterator_all_new())) {
         return CLI_FAILURE;
      }
      for (; iter && (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
         ast_channel_lock(c);
         ast_cli(a->fd, "Requested Hangup on channel '%s'\n", c->name);
         ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
         ast_channel_unlock(c);
      }
      ast_channel_iterator_destroy(iter);
   } else if ((c = ast_channel_get_by_name(a->argv[3]))) {
      ast_channel_lock(c);
      ast_cli(a->fd, "Requested Hangup on channel '%s'\n", c->name);
      ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
      ast_channel_unlock(c);
      c = ast_channel_unref(c);
   } else {
      ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
   }

   return CLI_SUCCESS;
}
static char* handle_unload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 593 of file cli.c.

References AST_FORCE_SOFT, CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_module_helper(), ast_cli_args::line, ast_cli_args::word, ast_cli_args::pos, ast_cli_args::n, ast_cli_args::argc, ast_cli_entry::args, CLI_SHOWUSAGE, ast_cli_args::argv, AST_FORCE_FIRM, AST_FORCE_HARD, ast_unload_resource(), ast_cli(), ast_cli_args::fd, CLI_FAILURE, and CLI_SUCCESS.

{
   /* "module unload mod_1 [mod_2 .. mod_N]" */
   int x;
   int force = AST_FORCE_SOFT;
   const char *s;

   switch (cmd) {
   case CLI_INIT:
      e->command = "module unload";
      e->usage =
         "Usage: module unload [-f|-h] <module_1> [<module_2> ... ]\n"
         "       Unloads the specified module from Asterisk. The -f\n"
         "       option causes the module to be unloaded even if it is\n"
         "       in use (may cause a crash) and the -h module causes the\n"
         "       module to be unloaded even if the module says it cannot, \n"
         "       which almost always will cause a crash.\n";
      return NULL;

   case CLI_GENERATE:
      return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);
   }
   if (a->argc < e->args + 1)
      return CLI_SHOWUSAGE;
   x = e->args;   /* first argument */
   s = a->argv[x];
   if (s[0] == '-') {
      if (s[1] == 'f')
         force = AST_FORCE_FIRM;
      else if (s[1] == 'h')
         force = AST_FORCE_HARD;
      else
         return CLI_SHOWUSAGE;
      if (a->argc < e->args + 2) /* need at least one module name */
         return CLI_SHOWUSAGE;
      x++;  /* skip this argument */
   }

   for (; x < a->argc; x++) {
      if (ast_unload_resource(a->argv[x], force)) {
         ast_cli(a->fd, "Unable to unload resource %s\n", a->argv[x]);
         return CLI_FAILURE;
      }
      ast_cli(a->fd, "Unloaded %s\n", a->argv[x]);
   }

   return CLI_SUCCESS;
}
static char* handle_verbose ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 386 of file cli.c.

References ast_cli_args::fd, ast_cli_args::argc, ast_cli_args::argv, S_OR, CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::pos, ast_strlen_zero(), ast_cli_args::n, complete_number(), ast_strdup, ast_complete_source_filename(), args, CLI_SHOWUSAGE, ast_cli_entry::args, option_debug, option_verbose, verbose_modules, AST_RWLIST_WRLOCK, AST_RWLIST_REMOVE_HEAD, ast_free, ast_clear_flag, ast_options, AST_OPT_FLAG_DEBUG_MODULE, AST_OPT_FLAG_VERBOSE_MODULE, AST_RWLIST_UNLOCK, ast_strdupa, find_module_level(), CLI_SUCCESS, AST_RWLIST_REMOVE, AST_RWLIST_EMPTY, ast_cli(), module_level::level, ast_calloc, CLI_FAILURE, AST_RWLIST_INSERT_TAIL, and ast_set_flag.

{
   int oldval;
   int newlevel;
   unsigned int is_debug;
   int atleast = 0;
   int fd = a->fd;
   int argc = a->argc;
   const char * const *argv = a->argv;
   const char *argv3 = a->argv ? S_OR(a->argv[3], "") : "";
   int *dst;
   char *what;
   struct module_level_list *mll;
   struct module_level *ml;

   switch (cmd) {
   case CLI_INIT:
      e->command = "core set {debug|verbose}";
      e->usage =
#if !defined(LOW_MEMORY)
         "Usage: core set {debug|verbose} [atleast] <level> [module]\n"
#else
         "Usage: core set {debug|verbose} [atleast] <level>\n"
#endif
         "       core set {debug|verbose} off\n"
#if !defined(LOW_MEMORY)
         "       Sets level of debug or verbose messages to be displayed or\n"
         "       sets a module name to display debug messages from.\n"
#else
         "       Sets level of debug or verbose messages to be displayed.\n"
#endif
         "  0 or off means no messages should be displayed.\n"
         "  Equivalent to -d[d[...]] or -v[v[v...]] on startup\n";
      return NULL;

   case CLI_GENERATE:
      if (a->pos == 3 || (a->pos == 4 && !strcasecmp(a->argv[3], "atleast"))) {
         const char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], "");
         int numbermatch = (ast_strlen_zero(pos) || strchr("123456789", pos[0])) ? 0 : 21;
         if (a->n < 21 && numbermatch == 0) {
            return complete_number(pos, 0, 0x7fffffff, a->n);
         } else if (pos[0] == '0') {
            if (a->n == 0) {
               return ast_strdup("0");
            } else {
               return NULL;
            }
         } else if (a->n == (21 - numbermatch)) {
            if (a->pos == 3 && !strncasecmp(argv3, "off", strlen(argv3))) {
               return ast_strdup("off");
            } else if (a->pos == 3 && !strncasecmp(argv3, "atleast", strlen(argv3))) {
               return ast_strdup("atleast");
            }
         } else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) {
            return ast_strdup("atleast");
         }
#if !defined(LOW_MEMORY)
      } else if (a->pos == 4 || (a->pos == 5 && !strcasecmp(argv3, "atleast"))) {
         return ast_complete_source_filename(a->pos == 4 ? S_OR(a->argv[4], "") : S_OR(a->argv[5], ""), a->n);
#endif
      }
      return NULL;
   }
   /* all the above return, so we proceed with the handler.
    * we are guaranteed to be called with argc >= e->args;
    */

   if (argc <= e->args)
      return CLI_SHOWUSAGE;
   if (!strcasecmp(argv[e->args - 1], "debug")) {
      dst = &option_debug;
      oldval = option_debug;
      what = "Core debug";
      is_debug = 1;
   } else {
      dst = &option_verbose;
      oldval = option_verbose;
      what = "Verbosity";
      is_debug = 0;
   }
   if (argc == e->args + 1 && !strcasecmp(argv[e->args], "off")) {
      newlevel = 0;

      mll = is_debug ? &debug_modules : &verbose_modules;

      AST_RWLIST_WRLOCK(mll);
      while ((ml = AST_RWLIST_REMOVE_HEAD(mll, entry))) {
         ast_free(ml);
      }
      ast_clear_flag(&ast_options, is_debug ? AST_OPT_FLAG_DEBUG_MODULE : AST_OPT_FLAG_VERBOSE_MODULE);
      AST_RWLIST_UNLOCK(mll);

      goto done;
   }
   if (!strcasecmp(argv[e->args], "atleast"))
      atleast = 1;
   if (argc != e->args + atleast + 1 && argc != e->args + atleast + 2)
      return CLI_SHOWUSAGE;
   if (sscanf(argv[e->args + atleast], "%30d", &newlevel) != 1)
      return CLI_SHOWUSAGE;
   if (argc == e->args + atleast + 2) {
      /* We have specified a module name. */
      char *mod = ast_strdupa(argv[e->args + atleast + 1]);

      if ((strlen(mod) > 3) && !strcasecmp(mod + strlen(mod) - 3, ".so")) {
         mod[strlen(mod) - 3] = '\0';
      }

      mll = is_debug ? &debug_modules : &verbose_modules;

      AST_RWLIST_WRLOCK(mll);

      ml = find_module_level(mod, is_debug);
      if (!newlevel) {
         if (!ml) {
            /* Specified off for a nonexistent entry. */
            AST_RWLIST_UNLOCK(mll);
            return CLI_SUCCESS;
         }
         AST_RWLIST_REMOVE(mll, ml, entry);
         if (AST_RWLIST_EMPTY(mll))
            ast_clear_flag(&ast_options, is_debug ? AST_OPT_FLAG_DEBUG_MODULE : AST_OPT_FLAG_VERBOSE_MODULE);
         AST_RWLIST_UNLOCK(mll);
         ast_cli(fd, "%s was %d and has been set to 0 for '%s'\n", what, ml->level, mod);
         ast_free(ml);
         return CLI_SUCCESS;
      }

      if (ml) {
         if ((atleast && newlevel < ml->level) || ml->level == newlevel) {
            ast_cli(fd, "%s is %d for '%s'\n", what, ml->level, mod);
            AST_RWLIST_UNLOCK(mll);
            return CLI_SUCCESS;
         }
         oldval = ml->level;
         ml->level = newlevel;
      } else {
         ml = ast_calloc(1, sizeof(*ml) + strlen(mod) + 1);
         if (!ml) {
            AST_RWLIST_UNLOCK(mll);
            return CLI_FAILURE;
         }
         oldval = ml->level;
         ml->level = newlevel;
         strcpy(ml->module, mod);
         AST_RWLIST_INSERT_TAIL(mll, ml, entry);
      }

      ast_set_flag(&ast_options, is_debug ? AST_OPT_FLAG_DEBUG_MODULE : AST_OPT_FLAG_VERBOSE_MODULE);

      AST_RWLIST_UNLOCK(mll);

      ast_cli(fd, "%s was %d and has been set to %d for '%s'\n", what, oldval, ml->level, ml->module);

      return CLI_SUCCESS;
   } else if (!newlevel) {
      /* Specified level as 0 instead of off. */
      mll = is_debug ? &debug_modules : &verbose_modules;

      AST_RWLIST_WRLOCK(mll);
      while ((ml = AST_RWLIST_REMOVE_HEAD(mll, entry))) {
         ast_free(ml);
      }
      ast_clear_flag(&ast_options, is_debug ? AST_OPT_FLAG_DEBUG_MODULE : AST_OPT_FLAG_VERBOSE_MODULE);
      AST_RWLIST_UNLOCK(mll);
   }

done:
   if (!atleast || newlevel > *dst)
      *dst = newlevel;
   if (oldval > 0 && *dst == 0)
      ast_cli(fd, "%s is now OFF\n", what);
   else if (*dst > 0) {
      if (oldval == *dst)
         ast_cli(fd, "%s is at least %d\n", what, *dst);
      else
         ast_cli(fd, "%s was %d and is now %d\n", what, oldval, *dst);
   }

   return CLI_SUCCESS;
}
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 2141 of file cli.c.

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

Referenced by handle_help().

{
   char matchstr[80] = "";
   struct ast_cli_entry *e = NULL;
   int len = 0;
   int found = 0;

   if (match) {
      ast_join(matchstr, sizeof(matchstr), match);
      len = strlen(matchstr);
   }
   if (!locked)
      AST_RWLIST_RDLOCK(&helpers);
   while ( (e = cli_next(e)) ) {
      /* Hide commands that start with '_' */
      if (e->_full_cmd[0] == '_')
         continue;
      if (match && strncasecmp(matchstr, e->_full_cmd, len))
         continue;
      ast_cli(fd, "%30.30s %s\n", e->_full_cmd, S_OR(e->summary, "<no description available>"));
      found++;
   }
   if (!locked)
      AST_RWLIST_UNLOCK(&helpers);
   if (!found && matchstr[0])
      ast_cli(fd, "No such command '%s'.\n", matchstr);
   return CLI_SUCCESS;
}
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 1913 of file cli.c.

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

Referenced by __ast_cli_generator().

{
   int lw;
   char *s, *t1;

   *actual = 0;
   if (ast_strlen_zero(token))
      return NULL;
   if (ast_strlen_zero(word))
      word = "";  /* dummy */
   lw = strlen(word);
   if (strcspn(word, cli_rsvd) != lw)
      return NULL;   /* no match if word has reserved chars */
   if (strchr(cli_rsvd, token[0]) == NULL) { /* regular match */
      if (strncasecmp(token, word, lw))   /* no match */
         return NULL;
      *actual = 1;
      return (pos != 0) ? NULL : ast_strdup(token);
   }
   /* now handle regexp match */

   /* Wildcard always matches, so we never do is_prefix on them */

   t1 = ast_strdupa(token + 1);  /* copy, skipping first char */
   while (pos >= 0 && (s = strsep(&t1, cli_rsvd)) && *s) {
      if (*s == '%') /* wildcard */
         continue;
      if (strncasecmp(s, word, lw)) /* no match */
         continue;
      (*actual)++;
      if (pos-- == 0)
         return ast_strdup(s);
   }
   return NULL;
}
static int modlist_modentry ( const char *  module,
const char *  description,
int  usecnt,
const char *  like 
) [static]

Definition at line 648 of file cli.c.

References strcasestr(), ast_cli(), and MODLIST_FORMAT.

Referenced by handle_modlist().

{
   /* Comparing the like with the module */
   if (strcasestr(module, like) ) {
      ast_cli(climodentryfd, MODLIST_FORMAT, module, description, usecnt);
      return 1;
   } 
   return 0;
}
static int more_words ( const char *const *  dst) [static]

returns true if there are more words to match

Definition at line 2347 of file cli.c.

Referenced by __ast_cli_generator().

{
   int i;
   for (i = 0; dst[i]; i++) {
      if (dst[i][0] != '[')
         return -1;
   }
   return 0;
}
static char* parse_args ( const char *  s,
int *  argc,
const char *  argv[],
int  max,
int *  trailingwhitespace 
) [static]

Definition at line 2216 of file cli.c.

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

Referenced by __ast_cli_generator(), and ast_cli_command_full().

{
   char *duplicate, *cur;
   int x = 0;
   int quoted = 0;
   int escaped = 0;
   int whitespace = 1;
   int dummy = 0;

   if (trailingwhitespace == NULL)
      trailingwhitespace = &dummy;
   *trailingwhitespace = 0;
   if (s == NULL) /* invalid, though! */
      return NULL;
   /* make a copy to store the parsed string */
   if (!(duplicate = ast_strdup(s)))
      return NULL;

   cur = duplicate;
   /* scan the original string copying into cur when needed */
   for (; *s ; s++) {
      if (x >= max - 1) {
         ast_log(LOG_WARNING, "Too many arguments, truncating at %s\n", s);
         break;
      }
      if (*s == '"' && !escaped) {
         quoted = !quoted;
         if (quoted && whitespace) {
            /* start a quoted string from previous whitespace: new argument */
            argv[x++] = cur;
            whitespace = 0;
         }
      } else if ((*s == ' ' || *s == '\t') && !(quoted || escaped)) {
         /* If we are not already in whitespace, and not in a quoted string or
            processing an escape sequence, and just entered whitespace, then
            finalize the previous argument and remember that we are in whitespace
         */
         if (!whitespace) {
            *cur++ = '\0';
            whitespace = 1;
         }
      } else if (*s == '\\' && !escaped) {
         escaped = 1;
      } else {
         if (whitespace) {
            /* we leave whitespace, and are not quoted. So it's a new argument */
            argv[x++] = cur;
            whitespace = 0;
         }
         *cur++ = *s;
         escaped = 0;
      }
   }
   /* Null terminate */
   *cur++ = '\0';
   /* XXX put a NULL in the last argument, because some functions that take
    * the array may want a null-terminated array.
    * argc still reflects the number of non-NULL entries.
    */
   argv[x] = NULL;
   *argc = x;
   *trailingwhitespace = whitespace;
   return duplicate;
}
static void print_uptimestr ( int  fd,
struct timeval  timeval,
const char *  prefix,
int  printsec 
) [static]

Definition at line 658 of file cli.c.

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

Referenced by handle_showuptime(), and handle_showcalls().

{
   int x; /* the main part - years, weeks, etc. */
   struct ast_str *out;

#define SECOND (1)
#define MINUTE (SECOND*60)
#define HOUR (MINUTE*60)
#define DAY (HOUR*24)
#define WEEK (DAY*7)
#define YEAR (DAY*365)
#define NEEDCOMMA(x) ((x)? ",": "") /* define if we need a comma */
   if (timeval.tv_sec < 0) /* invalid, nothing to show */
      return;

   if (printsec)  {  /* plain seconds output */
      ast_cli(fd, "%s: %lu\n", prefix, (u_long)timeval.tv_sec);
      return;
   }
   out = ast_str_alloca(256);
   if (timeval.tv_sec > YEAR) {
      x = (timeval.tv_sec / YEAR);
      timeval.tv_sec -= (x * YEAR);
      ast_str_append(&out, 0, "%d year%s%s ", x, ESS(x),NEEDCOMMA(timeval.tv_sec));
   }
   if (timeval.tv_sec > WEEK) {
      x = (timeval.tv_sec / WEEK);
      timeval.tv_sec -= (x * WEEK);
      ast_str_append(&out, 0, "%d week%s%s ", x, ESS(x),NEEDCOMMA(timeval.tv_sec));
   }
   if (timeval.tv_sec > DAY) {
      x = (timeval.tv_sec / DAY);
      timeval.tv_sec -= (x * DAY);
      ast_str_append(&out, 0, "%d day%s%s ", x, ESS(x),NEEDCOMMA(timeval.tv_sec));
   }
   if (timeval.tv_sec > HOUR) {
      x = (timeval.tv_sec / HOUR);
      timeval.tv_sec -= (x * HOUR);
      ast_str_append(&out, 0, "%d hour%s%s ", x, ESS(x),NEEDCOMMA(timeval.tv_sec));
   }
   if (timeval.tv_sec > MINUTE) {
      x = (timeval.tv_sec / MINUTE);
      timeval.tv_sec -= (x * MINUTE);
      ast_str_append(&out, 0, "%d minute%s%s ", x, ESS(x),NEEDCOMMA(timeval.tv_sec));
   }
   x = timeval.tv_sec;
   if (x > 0 || ast_str_strlen(out) == 0) /* if there is nothing, print 0 seconds */
      ast_str_append(&out, 0, "%d second%s ", x, ESS(x));
   ast_cli(fd, "%s: %s\n", prefix, ast_str_buffer(out));
}
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 1700 of file cli.c.

References ast_join(), ast_cli_entry::cmda, ast_cli_entry::_full_cmd, ast_strdup, ast_log(), LOG_WARNING, ast_cli_entry::cmdlen, and ast_cli_entry::args.

Referenced by __ast_cli_register().

{
   int i;
   char buf[80];

   ast_join(buf, sizeof(buf), e->cmda);
   e->_full_cmd = ast_strdup(buf);
   if (!e->_full_cmd) {
      ast_log(LOG_WARNING, "-- cannot allocate <%s>\n", buf);
      return -1;
   }
   e->cmdlen = strcspn(e->_full_cmd, cli_rsvd);
   for (i = 0; e->cmda[i]; i++)
      ;
   e->args = i;
   return 0;
}
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 1874 of file cli.c.

References ast_strlen_zero(), and strcasestr().

Referenced by find_cli(), and __ast_cli_generator().

{
   int l;
   char *pos;

   if (ast_strlen_zero(cmd) || ast_strlen_zero(cli_word))
      return -1;
   if (!strchr(cli_rsvd, cli_word[0])) /* normal match */
      return (strcasecmp(cmd, cli_word) == 0) ? 1 : -1;
   l = strlen(cmd);
   /* wildcard match - will extend in the future */
   if (l > 0 && cli_word[0] == '%') {
      return 1;   /* wildcard */
   }

   /* Start a search for the command entered against the cli word in question */
   pos = strcasestr(cli_word, cmd);
   while (pos) {

      /*
       *Check if the word matched with is surrounded by reserved characters on both sides
       * and isn't at the beginning of the cli_word since that would make it check in a location we shouldn't know about.
       * If it is surrounded by reserved chars and isn't at the beginning, it's a match.
       */
      if (pos != cli_word && strchr(cli_rsvd, pos[-1]) && strchr(cli_rsvd, pos[l])) {
         return 1;   /* valid match */
      }

      /* Ok, that one didn't match, strcasestr to the next appearance of the command and start over.*/
      pos = strcasestr(pos + 1, cmd);
   }
   /* If no matches were found over the course of the while loop, we hit the end of the string. It's a mismatch. */
   return -1;
}

Variable Documentation

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

Definition at line 97 of file cli.c.

struct ast_cli_entry cli_cli[] [static]

Definition at line 1644 of file cli.c.

int cli_default_perm = 1 [static]

Default permissions value 1=Permit 0=Deny.

Definition at line 73 of file cli.c.

Referenced by cli_has_permissions().

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

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

Definition at line 1694 of file cli.c.

int climodentryfd = -1 [static]

Definition at line 646 of file cli.c.

ast_mutex_t climodentrylock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 645 of file cli.c.

Referenced by handle_modlist().

list of module names and their debug levels

Definition at line 93 of file cli.c.

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

CLI permissions config file.

Definition at line 71 of file cli.c.

Referenced by ast_cli_perms_init().

ast_mutex_t permsconfiglock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

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

Definition at line 77 of file cli.c.

list of module names and their verbose levels

Definition at line 95 of file cli.c.

Referenced by find_module_level(), and handle_verbose().