Fri Nov 12 11:58:16 2010

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 dependency graph for cli.c:

Go to the source code of this file.

Data Structures

struct  ast_debug_file
 map a debug or verbose value to a filename More...
struct  cli_perm
 List of restrictions per user. More...
struct  cli_perm_head
struct  cli_perms
 List of users and permissions. More...
struct  debug_file_list
struct  helpers
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!%d!%s!%s!%s\n"
#define DAY   (HOUR*24)
#define FORMAT_STRING   "%-25s %-20s %-20s\n"
#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 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 %-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 %-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, 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_file (const char *file)
 Get the debug level for a file.
unsigned int ast_verbose_get_by_file (const char *file)
 Get the debug level for a file.
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 (char *argv[])
static struct ast_cli_entryfind_cli (char *const cmds[], int match_type)
static struct ast_debug_filefind_debug_file (const char *fn, 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_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_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, char *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 (char *const *dst)
 returns true if there are more words to match
static char * parse_args (const char *s, int *argc, 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 const char cli_rsvd [] = "[]{}|*%"
static int climodentryfd = -1
static ast_mutex_t climodentrylock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static struct debug_file_list debug_files
static const char perms_config [] = "cli_permissions.conf"
 CLI permissions config file.
static ast_mutex_t permsconfiglock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
 mutex used to prevent a user from running the 'cli reload permissions' command while it is already running.
static struct debug_file_list verbose_files

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 99 of file cli.c.

Referenced by ast_cli().

#define CONCISE_FORMAT_STRING   "%s!%s!%s!%d!%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   "%-25s %-20s %-20s\n"
#define FORMAT_STRING   "%-20.20s %-20.20s %-7.7s %-30.30s\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 590 of file cli.c.

Referenced by modlist_modentry().

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

Definition at line 591 of file cli.c.

Referenced by handle_modlist().

#define NEEDCOMMA (  )     ((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 %-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 %-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 2171 of file cli.c.

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

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

02172 {
02173    char *argv[AST_MAX_ARGS];
02174    struct ast_cli_entry *e = NULL;
02175    int x = 0, argindex, matchlen;
02176    int matchnum=0;
02177    char *ret = NULL;
02178    char matchstr[80] = "";
02179    int tws = 0;
02180    /* Split the argument into an array of words */
02181    char *duplicate = parse_args(text, &x, argv, ARRAY_LEN(argv), &tws);
02182 
02183    if (!duplicate)   /* malloc error */
02184       return NULL;
02185 
02186    /* Compute the index of the last argument (could be an empty string) */
02187    argindex = (!ast_strlen_zero(word) && x>0) ? x-1 : x;
02188 
02189    /* rebuild the command, ignore terminating white space and flatten space */
02190    ast_join(matchstr, sizeof(matchstr)-1, argv);
02191    matchlen = strlen(matchstr);
02192    if (tws) {
02193       strcat(matchstr, " "); /* XXX */
02194       if (matchlen)
02195          matchlen++;
02196    }
02197    if (lock)
02198       AST_RWLIST_RDLOCK(&helpers);
02199    while ( (e = cli_next(e)) ) {
02200       /* XXX repeated code */
02201       int src = 0, dst = 0, n = 0;
02202 
02203       if (e->command[0] == '_')
02204          continue;
02205 
02206       /*
02207        * Try to match words, up to and excluding the last word, which
02208        * is either a blank or something that we want to extend.
02209        */
02210       for (;src < argindex; dst++, src += n) {
02211          n = word_match(argv[src], e->cmda[dst]);
02212          if (n < 0)
02213             break;
02214       }
02215 
02216       if (src != argindex && more_words(e->cmda + dst))  /* not a match */
02217          continue;
02218       ret = is_prefix(argv[src], e->cmda[dst], state - matchnum, &n);
02219       matchnum += n; /* this many matches here */
02220       if (ret) {
02221          /*
02222           * argv[src] is a valid prefix of the next word in this
02223           * command. If this is also the correct entry, return it.
02224           */
02225          if (matchnum > state)
02226             break;
02227          ast_free(ret);
02228          ret = NULL;
02229       } else if (ast_strlen_zero(e->cmda[dst])) {
02230          /*
02231           * This entry is a prefix of the command string entered
02232           * (only one entry in the list should have this property).
02233           * Run the generator if one is available. In any case we are done.
02234           */
02235          if (e->handler) { /* new style command */
02236             struct ast_cli_args a = {
02237                .line = matchstr, .word = word,
02238                .pos = argindex,
02239                .n = state - matchnum,
02240                .argv = argv,
02241                .argc = x};
02242             ret = e->handler(e, CLI_GENERATE, &a);
02243          }
02244          if (ret)
02245             break;
02246       }
02247    }
02248    if (lock)
02249       AST_RWLIST_UNLOCK(&helpers);
02250    ast_free(duplicate);
02251    return ret;
02252 }

static int __ast_cli_register ( struct ast_cli_entry e,
struct ast_cli_entry ed 
) [static]

Definition at line 1858 of file cli.c.

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

Referenced by ast_cli_register().

01859 {
01860    struct ast_cli_entry *cur;
01861    int i, lf, ret = -1;
01862 
01863    struct ast_cli_args a;  /* fake argument */
01864    char **dst = (char **)e->cmda;   /* need to cast as the entry is readonly */
01865    char *s;
01866 
01867    memset(&a, '\0', sizeof(a));
01868    e->handler(e, CLI_INIT, &a);
01869    /* XXX check that usage and command are filled up */
01870    s = ast_skip_blanks(e->command);
01871    s = e->command = ast_strdup(s);
01872    for (i=0; !ast_strlen_zero(s) && i < AST_MAX_CMD_LEN-1; i++) {
01873       *dst++ = s; /* store string */
01874       s = ast_skip_nonblanks(s);
01875       if (*s == '\0')   /* we are done */
01876          break;
01877       *s++ = '\0';
01878       s = ast_skip_blanks(s);
01879    }
01880    *dst++ = NULL;
01881    
01882    AST_RWLIST_WRLOCK(&helpers);
01883    
01884    if (find_cli(e->cmda, 1)) {
01885       ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n", S_OR(e->_full_cmd, e->command));
01886       goto done;
01887    }
01888    if (set_full_cmd(e))
01889       goto done;
01890 
01891    lf = e->cmdlen;
01892    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&helpers, cur, list) {
01893       int len = cur->cmdlen;
01894       if (lf < len)
01895          len = lf;
01896       if (strncasecmp(e->_full_cmd, cur->_full_cmd, len) < 0) {
01897          AST_RWLIST_INSERT_BEFORE_CURRENT(e, list); 
01898          break;
01899       }
01900    }
01901    AST_RWLIST_TRAVERSE_SAFE_END;
01902 
01903    if (!cur)
01904       AST_RWLIST_INSERT_TAIL(&helpers, e, list); 
01905    ret = 0; /* success */
01906 
01907 done:
01908    AST_RWLIST_UNLOCK(&helpers);
01909 
01910    return ret;
01911 }

static int __ast_cli_unregister ( struct ast_cli_entry e,
struct ast_cli_entry ed 
) [static]

Definition at line 1836 of file cli.c.

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

Referenced by ast_cli_unregister().

01837 {
01838    if (e->inuse) {
01839       ast_log(LOG_WARNING, "Can't remove command that is in use\n");
01840    } else {
01841       AST_RWLIST_WRLOCK(&helpers);
01842       AST_RWLIST_REMOVE(&helpers, e, list);
01843       AST_RWLIST_UNLOCK(&helpers);
01844       ast_free(e->_full_cmd);
01845       e->_full_cmd = NULL;
01846       if (e->handler) {
01847          /* this is a new-style entry. Reset fields and free memory. */
01848          char *cmda = (char *) e->cmda;
01849          memset(cmda, '\0', sizeof(e->cmda));
01850          ast_free(e->command);
01851          e->command = NULL;
01852          e->usage = NULL;
01853       }
01854    }
01855    return 0;
01856 }

static void __init_ast_cli_buf ( void   )  [static]

Definition at line 96 of file cli.c.

00102 {

void ast_builtins_init ( void   ) 

initialize the _full_cmd string in * each of the builtins.

Provided by cli.c

Definition at line 1678 of file cli.c.

References ARRAY_LEN, and ast_cli_register_multiple().

Referenced by main().

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

Definition at line 101 of file cli.c.

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

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

00102 {
00103    int res;
00104    struct ast_str *buf;
00105    va_list ap;
00106 
00107    if (!(buf = ast_str_thread_get(&ast_cli_buf, AST_CLI_INITLEN)))
00108       return;
00109 
00110    va_start(ap, fmt);
00111    res = ast_str_set_va(&buf, 0, fmt, ap);
00112    va_end(ap);
00113 
00114    if (res != AST_DYNSTR_BUILD_FAILED) {
00115       ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100);
00116    }
00117 }

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:
uid User ID that is trying to run the command.
gid Group ID that is trying to run the command.
fd pipe
s incoming string
Return values:
0 on success
-1 on failure

Definition at line 2259 of file cli.c.

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

Referenced by ast_cli_command_multiple_full().

02260 {
02261    char *args[AST_MAX_ARGS + 1];
02262    struct ast_cli_entry *e;
02263    int x;
02264    char *duplicate = parse_args(s, &x, args + 1, AST_MAX_ARGS, NULL);
02265    char tmp[AST_MAX_ARGS + 1];
02266    char *retval = NULL;
02267    struct ast_cli_args a = {
02268       .fd = fd, .argc = x, .argv = args+1 };
02269 
02270    if (duplicate == NULL)
02271       return -1;
02272 
02273    if (x < 1)  /* We need at least one entry, otherwise ignore */
02274       goto done;
02275 
02276    AST_RWLIST_RDLOCK(&helpers);
02277    e = find_cli(args + 1, 0);
02278    if (e)
02279       ast_atomic_fetchadd_int(&e->inuse, 1);
02280    AST_RWLIST_UNLOCK(&helpers);
02281    if (e == NULL) {
02282       ast_cli(fd, "No such command '%s' (type 'core show help %s' for other possible commands)\n", s, find_best(args + 1));
02283       goto done;
02284    }
02285 
02286    ast_join(tmp, sizeof(tmp), args + 1);
02287    /* Check if the user has rights to run this command. */
02288    if (!cli_has_permissions(uid, gid, tmp)) {
02289       ast_cli(fd, "You don't have permissions to run '%s' command\n", tmp);
02290       ast_free(duplicate);
02291       return 0;
02292    }
02293 
02294    /*
02295     * Within the handler, argv[-1] contains a pointer to the ast_cli_entry.
02296     * Remember that the array returned by parse_args is NULL-terminated.
02297     */
02298    args[0] = (char *)e;
02299 
02300    retval = e->handler(e, CLI_HANDLER, &a);
02301 
02302    if (retval == CLI_SHOWUSAGE) {
02303       ast_cli(fd, "%s", S_OR(e->usage, "Invalid usage, but no usage information available.\n"));
02304    } else {
02305       if (retval == CLI_FAILURE)
02306          ast_cli(fd, "Command '%s' failed.\n", s);
02307    }
02308    ast_atomic_fetchadd_int(&e->inuse, -1);
02309 done:
02310    ast_free(duplicate);
02311    return 0;
02312 }

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:
uid User ID that is trying to run the command.
gid Group ID that is trying to run the command.
fd pipe
size is the total size of the string
s incoming string
Return values:
number of commands executed

Definition at line 2314 of file cli.c.

References ast_cli_command_full().

Referenced by netconsole().

02315 {
02316    char cmd[512];
02317    int x, y = 0, count = 0;
02318 
02319    for (x = 0; x < size; x++) {
02320       cmd[y] = s[x];
02321       y++;
02322       if (s[x] == '\0') {
02323          ast_cli_command_full(uid, gid, fd, cmd);
02324          y = 0;
02325          count++;
02326       }
02327    }
02328    return count;
02329 }

char* ast_cli_complete ( const char *  word,
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 char *choices = { "one", "two", "three", NULL };
   if (pos == 2)
         return ast_cli_complete(word, choices, n);
   else
      return NULL;
    }

Definition at line 1379 of file cli.c.

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

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

01380 {
01381    int i, which = 0, len;
01382    len = ast_strlen_zero(word) ? 0 : strlen(word);
01383 
01384    for (i = 0; choices[i]; i++) {
01385       if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state)
01386          return ast_strdup(choices[i]);
01387    }
01388    return NULL;
01389 }

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 2110 of file cli.c.

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

Referenced by cli_complete(), and handle_commandmatchesarray().

02111 {
02112    char **match_list = NULL, *retstr, *prevstr;
02113    size_t match_list_len, max_equal, which, i;
02114    int matches = 0;
02115 
02116    /* leave entry 0 free for the longest common substring */
02117    match_list_len = 1;
02118    while ((retstr = ast_cli_generator(text, word, matches)) != NULL) {
02119       if (matches + 1 >= match_list_len) {
02120          match_list_len <<= 1;
02121          if (!(match_list = ast_realloc(match_list, match_list_len * sizeof(*match_list))))
02122             return NULL;
02123       }
02124       match_list[++matches] = retstr;
02125    }
02126 
02127    if (!match_list)
02128       return match_list; /* NULL */
02129 
02130    /* Find the longest substring that is common to all results
02131     * (it is a candidate for completion), and store a copy in entry 0.
02132     */
02133    prevstr = match_list[1];
02134    max_equal = strlen(prevstr);
02135    for (which = 2; which <= matches; which++) {
02136       for (i = 0; i < max_equal && toupper(prevstr[i]) == toupper(match_list[which][i]); i++)
02137          continue;
02138       max_equal = i;
02139    }
02140 
02141    if (!(retstr = ast_malloc(max_equal + 1)))
02142       return NULL;
02143    
02144    ast_copy_string(retstr, match_list[1], max_equal + 1);
02145    match_list[0] = retstr;
02146 
02147    /* ensure that the array is NULL terminated */
02148    if (matches + 1 >= match_list_len) {
02149       if (!(match_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(*match_list))))
02150          return NULL;
02151    }
02152    match_list[matches + 1] = NULL;
02153 
02154    return match_list;
02155 }

char* ast_cli_generator ( const char *  ,
const char *  ,
int   
)

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

Return values:
0 on success
-1 on failure

Definition at line 2254 of file cli.c.

References __ast_cli_generator().

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

02255 {
02256    return __ast_cli_generator(text, word, state, 1);
02257 }

int ast_cli_generatornummatches ( const char *  text,
const char *  word 
)

Return the number of unique matches for the generator.

Definition at line 2093 of file cli.c.

References ast_cli_generator(), ast_free, and buf.

Referenced by handle_commandnummatches().

02094 {
02095    int matches = 0, i = 0;
02096    char *buf = NULL, *oldbuf = NULL;
02097 
02098    while ((buf = ast_cli_generator(text, word, i++))) {
02099       if (!oldbuf || strcmp(buf,oldbuf))
02100          matches++;
02101       if (oldbuf)
02102          ast_free(oldbuf);
02103       oldbuf = buf;
02104    }
02105    if (oldbuf)
02106       ast_free(oldbuf);
02107    return matches;
02108 }

int ast_cli_perms_init ( int  reload  ) 

Provided by cli.c

Definition at line 1555 of file cli.c.

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

Referenced by handle_cli_reload_permissions(), and main().

01556 {
01557    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01558    struct ast_config *cfg;
01559    char *cat = NULL;
01560    struct ast_variable *v;
01561    struct usergroup_cli_perm *user_group, *cp_entry;
01562    struct cli_perm *perm = NULL;
01563    struct passwd *pw;
01564    struct group *gr;
01565 
01566    if (ast_mutex_trylock(&permsconfiglock)) {
01567       ast_log(LOG_NOTICE, "You must wait until last 'cli reload permissions' command finish\n");
01568       return 1;
01569    }
01570 
01571    cfg = ast_config_load2(perms_config, "" /* core, can't reload */, config_flags);
01572    if (!cfg) {
01573       ast_mutex_unlock(&permsconfiglock);
01574       return 1;
01575    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
01576       ast_mutex_unlock(&permsconfiglock);
01577       return 0;
01578    }
01579 
01580    /* free current structures. */
01581    destroy_user_perms();
01582 
01583    while ((cat = ast_category_browse(cfg, cat))) {
01584       if (!strcasecmp(cat, "general")) {
01585          /* General options */
01586          for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
01587             if (!strcasecmp(v->name, "default_perm")) {
01588                cli_default_perm = (!strcasecmp(v->value, "permit")) ? 1: 0;
01589             }
01590          }
01591          continue;
01592       }
01593 
01594       /* users or groups */
01595       gr = NULL, pw = NULL;
01596       if (cat[0] == '@') {
01597          /* This is a group */
01598          gr = getgrnam(&cat[1]);
01599          if (!gr) {
01600             ast_log (LOG_WARNING, "Unknown group '%s'\n", &cat[1]);
01601             continue;
01602          }
01603       } else {
01604          /* This is a user */
01605          pw = getpwnam(cat);
01606          if (!pw) {
01607             ast_log (LOG_WARNING, "Unknown user '%s'\n", cat);
01608             continue;
01609          }
01610       }
01611       user_group = NULL;
01612       /* Check for duplicates */
01613       AST_RWLIST_WRLOCK(&cli_perms);
01614       AST_LIST_TRAVERSE(&cli_perms, cp_entry, list) {
01615          if ((pw && cp_entry->uid == pw->pw_uid) || (gr && cp_entry->gid == gr->gr_gid)) {
01616             /* if it is duplicated, just added this new settings, to 
01617             the current list. */
01618             user_group = cp_entry;
01619             break;
01620          }
01621       }
01622       AST_RWLIST_UNLOCK(&cli_perms);
01623 
01624       if (!user_group) {
01625          /* alloc space for the new user config. */
01626          user_group = ast_calloc(1, sizeof(*user_group));
01627          if (!user_group) {
01628             continue;
01629          }
01630          user_group->uid = (pw ? pw->pw_uid : -1);
01631          user_group->gid = (gr ? gr->gr_gid : -1);
01632          user_group->perms = ast_calloc(1, sizeof(*user_group->perms));
01633          if (!user_group->perms) {
01634             ast_free(user_group);
01635             continue;
01636          }
01637       }
01638       for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
01639          if (ast_strlen_zero(v->value)) {
01640             /* we need to check this condition cause it could break security. */
01641             ast_log(LOG_WARNING, "Empty permit/deny option in user '%s'\n", cat);
01642             continue;
01643          }
01644          if (!strcasecmp(v->name, "permit")) {
01645             perm = ast_calloc(1, sizeof(*perm));
01646             if (perm) {
01647                perm->permit = 1;
01648                perm->command = ast_strdup(v->value);
01649             }
01650          } else if (!strcasecmp(v->name, "deny")) {
01651             perm = ast_calloc(1, sizeof(*perm));
01652             if (perm) {
01653                perm->permit = 0;
01654                perm->command = ast_strdup(v->value);
01655             }
01656          } else {
01657             /* up to now, only 'permit' and 'deny' are possible values. */
01658             ast_log(LOG_WARNING, "Unknown '%s' option\n", v->name);
01659             continue;
01660          }
01661          if (perm) {
01662             /* Added the permission to the user's list. */
01663             AST_LIST_INSERT_TAIL(user_group->perms, perm, list);
01664             perm = NULL;
01665          }
01666       }
01667       AST_RWLIST_WRLOCK(&cli_perms);
01668       AST_RWLIST_INSERT_TAIL(&cli_perms, user_group, list);
01669       AST_RWLIST_UNLOCK(&cli_perms);
01670    }
01671 
01672    ast_config_destroy(cfg);
01673    ast_mutex_unlock(&permsconfiglock);
01674    return 0;
01675 }

int ast_cli_register ( struct ast_cli_entry e  ) 

Registers a command or an array of commands.

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

Definition at line 1920 of file cli.c.

References __ast_cli_register().

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

01921 {
01922    return __ast_cli_register(e, NULL);
01923 }

int ast_cli_register_multiple ( struct ast_cli_entry e,
int  len 
)

Register multiple commands.

Parameters:
e pointer to first cli entry to register
len number of entries to register

Definition at line 1928 of file cli.c.

References ast_cli_register().

Referenced by __ast_mm_init(), __ast_register_translator(), __init_manager(), ast_ais_clm_load_module(), ast_ais_evt_load_module(), ast_builtins_init(), ast_channels_init(), ast_features_init(), ast_file_init(), ast_http_init(), ast_image_init(), ast_indications_init(), ast_rtp_init(), ast_timing_init(), ast_tps_init(), ast_udptl_init(), ast_utils_init(), astdb_init(), astobj2_init(), crypto_init(), iax_provision_init(), init_framer(), init_logger(), load_module(), load_pbx(), main(), and register_config_cli().

01929 {
01930    int i, res = 0;
01931 
01932    for (i = 0; i < len; i++)
01933       res |= ast_cli_register(e + i);
01934 
01935    return res;
01936 }

int ast_cli_unregister ( struct ast_cli_entry e  ) 

Unregisters a command or an array of commands.

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

Definition at line 1914 of file cli.c.

References __ast_cli_unregister().

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

01915 {
01916    return __ast_cli_unregister(e, NULL);
01917 }

int ast_cli_unregister_multiple ( struct ast_cli_entry e,
int  len 
)

Unregister multiple commands.

Parameters:
e pointer to first cli entry to unregister
len number of entries to unregister

Definition at line 1938 of file cli.c.

References ast_cli_unregister().

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

01939 {
01940    int i, res = 0;
01941 
01942    for (i = 0; i < len; i++)
01943       res |= ast_cli_unregister(e + i);
01944 
01945    return res;
01946 }

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 1391 of file cli.c.

References ast_channel_unlock, ast_channel_walk_locked(), ast_strdup, and ast_channel::name.

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

01392 {
01393    struct ast_channel *c = NULL;
01394    int which = 0;
01395    int wordlen;
01396    char notfound = '\0';
01397    char *ret = &notfound; /* so NULL can break the loop */
01398 
01399    if (pos != rpos)
01400       return NULL;
01401 
01402    wordlen = strlen(word); 
01403 
01404    while (ret == &notfound && (c = ast_channel_walk_locked(c))) {
01405       if (!strncasecmp(word, c->name, wordlen) && ++which > state)
01406          ret = ast_strdup(c->name);
01407       ast_channel_unlock(c);
01408    }
01409    return ret == &notfound ? NULL : ret;
01410 }

unsigned int ast_debug_get_by_file ( const char *  file  ) 

Get the debug level for a file.

Parameters:
file the filename
Returns:
the debug level

Definition at line 119 of file cli.c.

References AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_debug_file::filename, and ast_debug_file::level.

00120 {
00121    struct ast_debug_file *adf;
00122    unsigned int res = 0;
00123 
00124    AST_RWLIST_RDLOCK(&debug_files);
00125    AST_LIST_TRAVERSE(&debug_files, adf, entry) {
00126       if (!strncasecmp(adf->filename, file, strlen(adf->filename))) {
00127          res = adf->level;
00128          break;
00129       }
00130    }
00131    AST_RWLIST_UNLOCK(&debug_files);
00132 
00133    return res;
00134 }

unsigned int ast_verbose_get_by_file ( const char *  file  ) 

Get the debug level for a file.

Parameters:
file the filename
Returns:
the debug level

Definition at line 136 of file cli.c.

References AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_debug_file::filename, and ast_debug_file::level.

00137 {
00138    struct ast_debug_file *adf;
00139    unsigned int res = 0;
00140 
00141    AST_RWLIST_RDLOCK(&verbose_files);
00142    AST_LIST_TRAVERSE(&verbose_files, adf, entry) {
00143       if (!strncasecmp(adf->filename, file, strlen(file))) {
00144          res = adf->level;
00145          break;
00146       }
00147    }
00148    AST_RWLIST_UNLOCK(&verbose_files);
00149 
00150    return res;
00151 }

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

Definition at line 166 of file cli.c.

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

Referenced by ast_cli_command_full(), and handle_cli_check_permissions().

00167 {
00168    struct usergroup_cli_perm *user_perm;
00169    struct cli_perm *perm;
00170    /* set to the default permissions general option. */
00171    int isallowg = cli_default_perm, isallowu = -1, ispattern;
00172    regex_t regexbuf;
00173 
00174    /* if uid == -1 or gid == -1 do not check permissions.
00175       if uid == -2 and gid == -2 is because rasterisk client didn't send
00176       the credentials, so the cli_default_perm will be applied. */
00177    if ((uid == CLI_NO_PERMS && gid == CLI_NO_PERMS) || command[0] == '_') {
00178       return 1;
00179    }
00180 
00181    if (gid < 0 && uid < 0) {
00182       return cli_default_perm;
00183    }
00184 
00185    AST_RWLIST_RDLOCK(&cli_perms);
00186    AST_LIST_TRAVERSE(&cli_perms, user_perm, list) {
00187       if (user_perm->gid != gid && user_perm->uid != uid) {
00188          continue;
00189       }
00190       AST_LIST_TRAVERSE(user_perm->perms, perm, list) {
00191          if (strcasecmp(perm->command, "all") && strncasecmp(perm->command, command, strlen(perm->command))) {
00192             /* if the perm->command is a pattern, check it against command. */
00193             ispattern = !regcomp(&regexbuf, perm->command, REG_EXTENDED | REG_NOSUB | REG_ICASE);
00194             if (ispattern && regexec(&regexbuf, command, 0, NULL, 0)) {
00195                regfree(&regexbuf);
00196                continue;
00197             }
00198             if (!ispattern) {
00199                continue;
00200             }
00201             regfree(&regexbuf);
00202          }
00203          if (user_perm->uid == uid) {
00204             /* this is a user definition. */
00205             isallowu = perm->permit;
00206          } else {
00207             /* otherwise is a group definition. */
00208             isallowg = perm->permit;
00209          }
00210       }
00211    }
00212    AST_RWLIST_UNLOCK(&cli_perms);
00213    if (isallowu > -1) {
00214       /* user definition override group definition. */
00215       isallowg = isallowu;
00216    }
00217 
00218    return isallowg;
00219 }

static struct ast_cli_entry* cli_next ( struct ast_cli_entry e  )  [static, read]

Definition at line 657 of file cli.c.

References AST_LIST_FIRST, and AST_LIST_NEXT.

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

00658 {
00659    if (e) {
00660       return AST_LIST_NEXT(e, list);
00661    } else {
00662       return AST_LIST_FIRST(&helpers);
00663    }
00664 }

static char* complete_fn ( const char *  word,
int  state 
) [static]

Definition at line 223 of file cli.c.

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

Referenced by handle_load().

00224 {
00225    char *c, *d;
00226    char filename[PATH_MAX];
00227 
00228    if (word[0] == '/')
00229       ast_copy_string(filename, word, sizeof(filename));
00230    else
00231       snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
00232 
00233    c = d = filename_completion_function(filename, state);
00234    
00235    if (c && word[0] != '/')
00236       c += (strlen(ast_config_AST_MODULE_DIR) + 1);
00237    if (c)
00238       c = ast_strdup(c);
00239 
00240    free(d);
00241    
00242    return c;
00243 }

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

Definition at line 322 of file cli.c.

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

Referenced by handle_verbose().

00323 {
00324    int i, count = 0;
00325    unsigned int prospective[2];
00326    unsigned int part = strtoul(partial, NULL, 10);
00327    char next[12];
00328 
00329    if (part < min || part > max) {
00330       return NULL;
00331    }
00332 
00333    for (i = 0; i < 21; i++) {
00334       if (i == 0) {
00335          prospective[0] = prospective[1] = part;
00336       } else if (part == 0 && !ast_strlen_zero(partial)) {
00337          break;
00338       } else if (i < 11) {
00339          prospective[0] = prospective[1] = part * 10 + (i - 1);
00340       } else {
00341          prospective[0] = (part * 10 + (i - 11)) * 10;
00342          prospective[1] = prospective[0] + 9;
00343       }
00344       if (i < 11 && (prospective[0] < min || prospective[0] > max)) {
00345          continue;
00346       } else if (prospective[1] < min || prospective[0] > max) {
00347          continue;
00348       }
00349 
00350       if (++count > n) {
00351          if (i < 11) {
00352             snprintf(next, sizeof(next), "%u", prospective[0]);
00353          } else {
00354             snprintf(next, sizeof(next), "%u...", prospective[0] / 10);
00355          }
00356          return ast_strdup(next);
00357       }
00358    }
00359    return NULL;
00360 }

static void destroy_user_perms ( void   )  [static]

cleanup (free) cli_perms linkedlist.

Definition at line 1539 of file cli.c.

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

Referenced by ast_cli_perms_init().

01540 {
01541    struct cli_perm *perm;
01542    struct usergroup_cli_perm *user_perm;
01543 
01544    AST_RWLIST_WRLOCK(&cli_perms);
01545    while ((user_perm = AST_LIST_REMOVE_HEAD(&cli_perms, list))) {
01546       while ((perm = AST_LIST_REMOVE_HEAD(user_perm->perms, list))) {
01547          ast_free(perm->command);
01548          ast_free(perm);
01549       }
01550       ast_free(user_perm);
01551    }
01552    AST_RWLIST_UNLOCK(&cli_perms);
01553 }

static char* find_best ( char *  argv[]  )  [static]

Definition at line 1817 of file cli.c.

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

Referenced by ast_cli_command_full().

01818 {
01819    static char cmdline[80];
01820    int x;
01821    /* See how close we get, then print the candidate */
01822    char *myargv[AST_MAX_CMD_LEN];
01823    for (x=0;x<AST_MAX_CMD_LEN;x++)
01824       myargv[x]=NULL;
01825    AST_RWLIST_RDLOCK(&helpers);
01826    for (x=0;argv[x];x++) {
01827       myargv[x] = argv[x];
01828       if (!find_cli(myargv, -1))
01829          break;
01830    }
01831    AST_RWLIST_UNLOCK(&helpers);
01832    ast_join(cmdline, sizeof(cmdline), myargv);
01833    return cmdline;
01834 }

static struct ast_cli_entry* find_cli ( char *const   cmds[],
int  match_type 
) [static, read]

Definition at line 1773 of file cli.c.

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

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

01774 {
01775    int matchlen = -1;   /* length of longest match so far */
01776    struct ast_cli_entry *cand = NULL, *e=NULL;
01777 
01778    while ( (e = cli_next(e)) ) {
01779       /* word-by word regexp comparison */
01780       char * const *src = cmds;
01781       char * const *dst = e->cmda;
01782       int n = 0;
01783       for (;; dst++, src += n) {
01784          n = word_match(*src, *dst);
01785          if (n < 0)
01786             break;
01787       }
01788       if (ast_strlen_zero(*dst) || ((*dst)[0] == '[' && ast_strlen_zero(dst[1]))) {
01789          /* no more words in 'e' */
01790          if (ast_strlen_zero(*src)) /* exact match, cannot do better */
01791             break;
01792          /* Here, cmds has more words than the entry 'e' */
01793          if (match_type != 0) /* but we look for almost exact match... */
01794             continue;   /* so we skip this one. */
01795          /* otherwise we like it (case 0) */
01796       } else { /* still words in 'e' */
01797          if (ast_strlen_zero(*src))
01798             continue; /* cmds is shorter than 'e', not good */
01799          /* Here we have leftover words in cmds and 'e',
01800           * but there is a mismatch. We only accept this one if match_type == -1
01801           * and this is the last word for both.
01802           */
01803          if (match_type != -1 || !ast_strlen_zero(src[1]) ||
01804              !ast_strlen_zero(dst[1])) /* not the one we look for */
01805             continue;
01806          /* good, we are in case match_type == -1 and mismatch on last word */
01807       }
01808       if (src - cmds > matchlen) {  /* remember the candidate */
01809          matchlen = src - cmds;
01810          cand = e;
01811       }
01812    }
01813 
01814    return e ? e : cand;
01815 }

static struct ast_debug_file* find_debug_file ( const char *  fn,
unsigned int  debug 
) [static, read]

Find the debug or verbose file setting.

  • debug 1 for debug, 0 for verbose

Definition at line 309 of file cli.c.

References AST_LIST_TRAVERSE, and ast_debug_file::filename.

Referenced by handle_verbose().

00310 {
00311    struct ast_debug_file *df = NULL;
00312    struct debug_file_list *dfl = debug ? &debug_files : &verbose_files;
00313 
00314    AST_LIST_TRAVERSE(dfl, df, entry) {
00315       if (!strcasecmp(df->filename, fn))
00316          break;
00317    }
00318 
00319    return df;
00320 }

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

Definition at line 1412 of file cli.c.

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

01413 {
01414 #define FORMAT_STRING  "%-25s  %-20s  %-20s\n"
01415 
01416    struct ast_group_info *gi = NULL;
01417    int numchans = 0;
01418    regex_t regexbuf;
01419    int havepattern = 0;
01420 
01421    switch (cmd) {
01422    case CLI_INIT:
01423       e->command = "group show channels";
01424       e->usage = 
01425          "Usage: group show channels [pattern]\n"
01426          "       Lists all currently active channels with channel group(s) specified.\n"
01427          "       Optional regular expression pattern is matched to group names for each\n"
01428          "       channel.\n";
01429       return NULL;
01430    case CLI_GENERATE:
01431       return NULL;
01432    }
01433 
01434    if (a->argc < 3 || a->argc > 4)
01435       return CLI_SHOWUSAGE;
01436    
01437    if (a->argc == 4) {
01438       if (regcomp(&regexbuf, a->argv[3], REG_EXTENDED | REG_NOSUB))
01439          return CLI_SHOWUSAGE;
01440       havepattern = 1;
01441    }
01442 
01443    ast_cli(a->fd, FORMAT_STRING, "Channel", "Group", "Category");
01444 
01445    ast_app_group_list_rdlock();
01446    
01447    gi = ast_app_group_list_head();
01448    while (gi) {
01449       if (!havepattern || !regexec(&regexbuf, gi->group, 0, NULL, 0)) {
01450          ast_cli(a->fd, FORMAT_STRING, gi->chan->name, gi->group, (ast_strlen_zero(gi->category) ? "(default)" : gi->category));
01451          numchans++;
01452       }
01453       gi = AST_LIST_NEXT(gi, group_list);
01454    }
01455    
01456    ast_app_group_list_unlock();
01457    
01458    if (havepattern)
01459       regfree(&regexbuf);
01460 
01461    ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
01462    return CLI_SUCCESS;
01463 #undef FORMAT_STRING
01464 }

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

Definition at line 791 of file cli.c.

References ast_channel::_state, ast_channel::accountcode, ast_channel::amaflags, ast_channel::appl, ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_active_calls(), ast_bridged_channel(), ast_channel_unlock, ast_channel_walk_locked(), ast_cli(), ast_processed_calls(), ast_state2str(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_channel::cdr, ast_channel::cid, ast_callerid::cid_num, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, CONCISE_FORMAT_STRING, ast_channel::context, ast_channel::data, ESS, ast_channel::exten, ast_cli_args::fd, FORMAT_STRING, FORMAT_STRING2, ast_channel::name, option_maxcalls, ast_channel::priority, S_OR, ast_cdr::start, ast_channel::uniqueid, ast_cli_entry::usage, VERBOSE_FORMAT_STRING, and VERBOSE_FORMAT_STRING2.

00792 {
00793 #define FORMAT_STRING  "%-20.20s %-20.20s %-7.7s %-30.30s\n"
00794 #define FORMAT_STRING2 "%-20.20s %-20.20s %-7.7s %-30.30s\n"
00795 #define CONCISE_FORMAT_STRING  "%s!%s!%s!%d!%s!%s!%s!%s!%s!%d!%s!%s!%s\n"
00796 #define VERBOSE_FORMAT_STRING  "%-20.20s %-20.20s %-16.16s %4d %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-20.20s\n"
00797 #define VERBOSE_FORMAT_STRING2 "%-20.20s %-20.20s %-16.16s %-4.4s %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-20.20s\n"
00798 
00799    struct ast_channel *c = NULL;
00800    int numchans = 0, concise = 0, verbose = 0, count = 0;
00801    int fd, argc;
00802    char **argv;
00803 
00804    switch (cmd) {
00805    case CLI_INIT:
00806       e->command = "core show channels [concise|verbose|count]";
00807       e->usage =
00808          "Usage: core show channels [concise|verbose|count]\n"
00809          "       Lists currently defined channels and some information about them. If\n"
00810          "       'concise' is specified, the format is abridged and in a more easily\n"
00811          "       machine parsable format. If 'verbose' is specified, the output includes\n"
00812          "       more and longer fields. If 'count' is specified only the channel and call\n"
00813          "       count is output.\n"
00814          "  The 'concise' option is deprecated and will be removed from future versions\n"
00815          "  of Asterisk.\n";
00816       return NULL;
00817 
00818    case CLI_GENERATE:
00819       return NULL;
00820    }
00821    fd = a->fd;
00822    argc = a->argc;
00823    argv = a->argv;
00824 
00825    if (a->argc == e->args) {
00826       if (!strcasecmp(argv[e->args-1],"concise"))
00827          concise = 1;
00828       else if (!strcasecmp(argv[e->args-1],"verbose"))
00829          verbose = 1;
00830       else if (!strcasecmp(argv[e->args-1],"count"))
00831          count = 1;
00832       else
00833          return CLI_SHOWUSAGE;
00834    } else if (a->argc != e->args - 1)
00835       return CLI_SHOWUSAGE;
00836 
00837    if (!count) {
00838       if (!concise && !verbose)
00839          ast_cli(fd, FORMAT_STRING2, "Channel", "Location", "State", "Application(Data)");
00840       else if (verbose)
00841          ast_cli(fd, VERBOSE_FORMAT_STRING2, "Channel", "Context", "Extension", "Priority", "State", "Application", "Data", 
00842             "CallerID", "Duration", "Accountcode", "BridgedTo");
00843    }
00844 
00845    while ((c = ast_channel_walk_locked(c)) != NULL) {
00846       struct ast_channel *bc = ast_bridged_channel(c);
00847       char durbuf[10] = "-";
00848 
00849       if (!count) {
00850          if ((concise || verbose)  && c->cdr && !ast_tvzero(c->cdr->start)) {
00851             int duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
00852             if (verbose) {
00853                int durh = duration / 3600;
00854                int durm = (duration % 3600) / 60;
00855                int durs = duration % 60;
00856                snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
00857             } else {
00858                snprintf(durbuf, sizeof(durbuf), "%d", duration);
00859             }           
00860          }
00861          if (concise) {
00862             ast_cli(fd, CONCISE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
00863                c->appl ? c->appl : "(None)",
00864                S_OR(c->data, ""),   /* XXX different from verbose ? */
00865                S_OR(c->cid.cid_num, ""),
00866                S_OR(c->accountcode, ""),
00867                c->amaflags, 
00868                durbuf,
00869                bc ? bc->name : "(None)",
00870                c->uniqueid);
00871          } else if (verbose) {
00872             ast_cli(fd, VERBOSE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
00873                c->appl ? c->appl : "(None)",
00874                c->data ? S_OR(c->data, "(Empty)" ): "(None)",
00875                S_OR(c->cid.cid_num, ""),
00876                durbuf,
00877                S_OR(c->accountcode, ""),
00878                bc ? bc->name : "(None)");
00879          } else {
00880             char locbuf[40] = "(None)";
00881             char appdata[40] = "(None)";
00882             
00883             if (!ast_strlen_zero(c->context) && !ast_strlen_zero(c->exten)) 
00884                snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", c->exten, c->context, c->priority);
00885             if (c->appl)
00886                snprintf(appdata, sizeof(appdata), "%s(%s)", c->appl, S_OR(c->data, ""));
00887             ast_cli(fd, FORMAT_STRING, c->name, locbuf, ast_state2str(c->_state), appdata);
00888          }
00889       }
00890       numchans++;
00891       ast_channel_unlock(c);
00892    }
00893    if (!concise) {
00894       ast_cli(fd, "%d active channel%s\n", numchans, ESS(numchans));
00895       if (option_maxcalls)
00896          ast_cli(fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
00897             ast_active_calls(), option_maxcalls, ESS(ast_active_calls()),
00898             ((double)ast_active_calls() / (double)option_maxcalls) * 100.0);
00899       else
00900          ast_cli(fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
00901 
00902       ast_cli(fd, "%d call%s processed\n", ast_processed_calls(), ESS(ast_processed_calls()));
00903    }
00904    return CLI_SUCCESS;
00905    
00906 #undef FORMAT_STRING
00907 #undef FORMAT_STRING2
00908 #undef CONCISE_FORMAT_STRING
00909 #undef VERBOSE_FORMAT_STRING
00910 #undef VERBOSE_FORMAT_STRING2
00911 }

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 1005 of file cli.c.

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

01006 {
01007    struct passwd *pw = NULL;
01008    struct group *gr;
01009    int gid = -1, uid = -1;
01010    char command[AST_MAX_ARGS] = "";
01011    struct ast_cli_entry *ce = NULL;
01012    int found = 0;
01013    char *group, *tmp;
01014 
01015    switch (cmd) {
01016    case CLI_INIT:
01017       e->command = "cli check permissions";
01018       e->usage =
01019          "Usage: cli check permissions {<username>|@<groupname>|<username>@<groupname>} [<command>]\n"
01020          "       Check permissions config for a user@group or list the allowed commands for the specified user.\n"
01021          "       The username or the groupname may be omitted.\n";
01022       return NULL;
01023    case CLI_GENERATE:
01024       if (a->pos >= 4) {
01025          return ast_cli_generator(a->line + strlen("cli check permissions") + strlen(a->argv[3]) + 1, a->word, a->n);
01026       }
01027       return NULL;
01028    }
01029 
01030    if (a->argc < 4) {
01031       return CLI_SHOWUSAGE;
01032    }
01033 
01034    tmp = ast_strdupa(a->argv[3]);
01035    group = strchr(tmp, '@');
01036    if (group) {
01037       gr = getgrnam(&group[1]);
01038       if (!gr) {
01039          ast_cli(a->fd, "Unknown group '%s'\n", &group[1]);
01040          return CLI_FAILURE;
01041       }
01042       group[0] = '\0';
01043       gid = gr->gr_gid;
01044    }
01045 
01046    if (!group && ast_strlen_zero(tmp)) {
01047       ast_cli(a->fd, "You didn't supply a username\n");
01048    } else if (!ast_strlen_zero(tmp) && !(pw = getpwnam(tmp))) {
01049       ast_cli(a->fd, "Unknown user '%s'\n", tmp);
01050       return CLI_FAILURE;
01051    } else if (pw) {
01052       uid = pw->pw_uid;
01053    }
01054 
01055    if (a->argc == 4) {
01056       while ((ce = cli_next(ce))) {
01057          /* Hide commands that start with '_' */
01058          if (ce->_full_cmd[0] == '_') {
01059             continue;
01060          }
01061          if (cli_has_permissions(uid, gid, ce->_full_cmd)) {
01062             ast_cli(a->fd, "%30.30s %s\n", ce->_full_cmd, S_OR(ce->summary, "<no description available>"));
01063             found++;
01064          }
01065       }
01066       if (!found) {
01067          ast_cli(a->fd, "You are not allowed to run any command on Asterisk\n");
01068       }
01069    } else {
01070       ast_join(command, sizeof(command), a->argv + 4);
01071       ast_cli(a->fd, "%s '%s%s%s' is %s to run command: '%s'\n", uid >= 0 ? "User" : "Group", tmp,
01072          group && uid >= 0 ? "@" : "",
01073          group ? &group[1] : "",
01074          cli_has_permissions(uid, gid, command) ? "allowed" : "not allowed", command);
01075    }
01076 
01077    return CLI_SUCCESS;
01078 }

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 986 of file cli.c.

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

00987 {
00988    switch (cmd) {
00989    case CLI_INIT:
00990       e->command = "cli reload permissions";
00991       e->usage =
00992          "Usage: cli reload permissions\n"
00993          "       Reload the 'cli_permissions.conf' file.\n";
00994       return NULL;
00995    case CLI_GENERATE:
00996       return NULL;
00997    }
00998 
00999    ast_cli_perms_init(1);
01000 
01001    return CLI_SUCCESS;
01002 }

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 941 of file cli.c.

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

00942 {
00943    struct usergroup_cli_perm *cp;
00944    struct cli_perm *perm;
00945    struct passwd *pw = NULL;
00946    struct group *gr = NULL;
00947 
00948    switch (cmd) {
00949    case CLI_INIT:
00950       e->command = "cli show permissions";
00951       e->usage =
00952          "Usage: cli show permissions\n"
00953          "       Shows CLI configured permissions.\n";
00954       return NULL;
00955    case CLI_GENERATE:
00956       return NULL;
00957    }
00958 
00959    AST_RWLIST_RDLOCK(&cli_perms);
00960    AST_LIST_TRAVERSE(&cli_perms, cp, list) {
00961       if (cp->uid >= 0) {
00962          pw = getpwuid(cp->uid);
00963          if (pw) {
00964             ast_cli(a->fd, "user: %s [uid=%d]\n", pw->pw_name, cp->uid);
00965          }
00966       } else {
00967          gr = getgrgid(cp->gid);
00968          if (gr) {
00969             ast_cli(a->fd, "group: %s [gid=%d]\n", gr->gr_name, cp->gid);
00970          }
00971       }
00972       ast_cli(a->fd, "Permissions:\n");
00973       if (cp->perms) {
00974          AST_LIST_TRAVERSE(cp->perms, perm, list) {
00975             ast_cli(a->fd, "\t%s -> %s\n", perm->permit ? "permit" : "deny", perm->command);
00976          }
00977       }
00978       ast_cli(a->fd, "\n");
00979    }
00980    AST_RWLIST_UNLOCK(&cli_perms);
00981 
00982    return CLI_SUCCESS;
00983 }

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

Definition at line 1163 of file cli.c.

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

01164 {
01165    char *buf;
01166    switch (cmd) {
01167    case CLI_INIT:
01168       e->command = "_command complete";
01169       e->usage = 
01170          "Usage: _command complete \"<line>\" text state\n"
01171          "       This function is used internally to help with command completion and should.\n"
01172          "       never be called by the user directly.\n";
01173       return NULL;
01174    case CLI_GENERATE:
01175       return NULL;
01176    }
01177    if (a->argc != 5)
01178       return CLI_SHOWUSAGE;
01179    buf = __ast_cli_generator(a->argv[2], a->argv[3], atoi(a->argv[4]), 0);
01180    if (buf) {
01181       ast_cli(a->fd, "%s", buf);
01182       ast_free(buf);
01183    } else
01184       ast_cli(a->fd, "NULL\n");
01185    return CLI_SUCCESS;
01186 }

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

Definition at line 1082 of file cli.c.

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

01083 {
01084    char *buf, *obuf;
01085    int buflen = 2048;
01086    int len = 0;
01087    char **matches;
01088    int x, matchlen;
01089    
01090    switch (cmd) {
01091    case CLI_INIT:
01092       e->command = "_command matchesarray";
01093       e->usage = 
01094          "Usage: _command matchesarray \"<line>\" text \n"
01095          "       This function is used internally to help with command completion and should.\n"
01096          "       never be called by the user directly.\n";
01097       return NULL;
01098    case CLI_GENERATE:
01099       return NULL;
01100    }
01101 
01102    if (a->argc != 4)
01103       return CLI_SHOWUSAGE;
01104    if (!(buf = ast_malloc(buflen)))
01105       return CLI_FAILURE;
01106    buf[len] = '\0';
01107    matches = ast_cli_completion_matches(a->argv[2], a->argv[3]);
01108    if (matches) {
01109       for (x=0; matches[x]; x++) {
01110          matchlen = strlen(matches[x]) + 1;
01111          if (len + matchlen >= buflen) {
01112             buflen += matchlen * 3;
01113             obuf = buf;
01114             if (!(buf = ast_realloc(obuf, buflen))) 
01115                /* Memory allocation failure...  Just free old buffer and be done */
01116                ast_free(obuf);
01117          }
01118          if (buf)
01119             len += sprintf( buf + len, "%s ", matches[x]);
01120          ast_free(matches[x]);
01121          matches[x] = NULL;
01122       }
01123       ast_free(matches);
01124    }
01125 
01126    if (buf) {
01127       ast_cli(a->fd, "%s%s",buf, AST_CLI_COMPLETE_EOF);
01128       ast_free(buf);
01129    } else
01130       ast_cli(a->fd, "NULL\n");
01131 
01132    return CLI_SUCCESS;
01133 }

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

Definition at line 1137 of file cli.c.

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

01138 {
01139    int matches = 0;
01140 
01141    switch (cmd) {
01142    case CLI_INIT:
01143       e->command = "_command nummatches";
01144       e->usage = 
01145          "Usage: _command nummatches \"<line>\" text \n"
01146          "       This function is used internally to help with command completion and should.\n"
01147          "       never be called by the user directly.\n";
01148       return NULL;
01149    case CLI_GENERATE:
01150       return NULL;
01151    }
01152 
01153    if (a->argc != 4)
01154       return CLI_SHOWUSAGE;
01155 
01156    matches = ast_cli_generatornummatches(a->argv[2], a->argv[3]);
01157 
01158    ast_cli(a->fd, "%d", matches);
01159 
01160    return CLI_SUCCESS;
01161 }

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

Definition at line 1188 of file cli.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_unlock, ast_channel_walk_locked(), ast_cli(), ast_complete_channels(), ast_get_channel_by_name_locked(), ast_strdup, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, DEBUGCHAN_FLAG, ast_cli_args::fd, ast_channel::fin, ast_channel::fout, global_fin, global_fout, ast_cli_args::line, ast_cli_args::n, ast_channel::name, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

Referenced by handle_nodebugchan_deprecated().

01189 {
01190    struct ast_channel *c = NULL;
01191    int is_all, is_off = 0;
01192 
01193    switch (cmd) {
01194    case CLI_INIT:
01195       e->command = "core set debug channel";
01196       e->usage =
01197          "Usage: core set debug channel <all|channel> [off]\n"
01198          "       Enables/disables debugging on all or on a specific channel.\n";
01199       return NULL;
01200 
01201    case CLI_GENERATE:
01202       /* XXX remember to handle the optional "off" */
01203       if (a->pos != e->args)
01204          return NULL;
01205       return a->n == 0 ? ast_strdup("all") : ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
01206    }
01207    /* 'core set debug channel {all|chan_id}' */
01208    if (a->argc == e->args + 2) {
01209       if (!strcasecmp(a->argv[e->args + 1], "off"))
01210          is_off = 1;
01211       else
01212          return CLI_SHOWUSAGE;
01213    } else if (a->argc != e->args + 1)
01214       return CLI_SHOWUSAGE;
01215 
01216    is_all = !strcasecmp("all", a->argv[e->args]);
01217    if (is_all) {
01218       if (is_off) {
01219          global_fin &= ~DEBUGCHAN_FLAG;
01220          global_fout &= ~DEBUGCHAN_FLAG;
01221       } else {
01222          global_fin |= DEBUGCHAN_FLAG;
01223          global_fout |= DEBUGCHAN_FLAG;
01224       }
01225       c = ast_channel_walk_locked(NULL);
01226    } else {
01227       c = ast_get_channel_by_name_locked(a->argv[e->args]);
01228       if (c == NULL)
01229          ast_cli(a->fd, "No such channel %s\n", a->argv[e->args]);
01230    }
01231    while (c) {
01232       if (!(c->fin & DEBUGCHAN_FLAG) || !(c->fout & DEBUGCHAN_FLAG)) {
01233          if (is_off) {
01234             c->fin &= ~DEBUGCHAN_FLAG;
01235             c->fout &= ~DEBUGCHAN_FLAG;
01236          } else {
01237             c->fin |= DEBUGCHAN_FLAG;
01238             c->fout |= DEBUGCHAN_FLAG;
01239          }
01240          ast_cli(a->fd, "Debugging %s on channel %s\n", is_off ? "disabled" : "enabled", c->name);
01241       }
01242       ast_channel_unlock(c);
01243       if (!is_all)
01244          break;
01245       c = ast_channel_walk_locked(c);
01246    }
01247    ast_cli(a->fd, "Debugging on new channels is %s\n", is_off ? "disabled" : "enabled");
01248    return CLI_SUCCESS;
01249 }

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

Definition at line 1981 of file cli.c.

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

01982 {
01983    char fullcmd[80];
01984    struct ast_cli_entry *my_e;
01985    char *res = CLI_SUCCESS;
01986 
01987    if (cmd == CLI_INIT) {
01988       e->command = "core show help";
01989       e->usage =
01990          "Usage: core show help [topic]\n"
01991          "       When called with a topic as an argument, displays usage\n"
01992          "       information on the given command. If called without a\n"
01993          "       topic, it provides a list of commands.\n";
01994       return NULL;
01995 
01996    } else if (cmd == CLI_GENERATE) {
01997       /* skip first 14 or 15 chars, "core show help " */
01998       int l = strlen(a->line);
01999 
02000       if (l > 15) {
02001          l = 15;
02002       }
02003       /* XXX watch out, should stop to the non-generator parts */
02004       return __ast_cli_generator(a->line + l, a->word, a->n, 0);
02005    }
02006    if (a->argc == e->args) {
02007       return help1(a->fd, NULL, 0);
02008    }
02009 
02010    AST_RWLIST_RDLOCK(&helpers);
02011    my_e = find_cli(a->argv + 3, 1); /* try exact match first */
02012    if (!my_e) {
02013       res = help1(a->fd, a->argv + 3, 1 /* locked */);
02014       AST_RWLIST_UNLOCK(&helpers);
02015       return res;
02016    }
02017    if (my_e->usage)
02018       ast_cli(a->fd, "%s", my_e->usage);
02019    else {
02020       ast_join(fullcmd, sizeof(fullcmd), a->argv + 3);
02021       ast_cli(a->fd, "No help text available for '%s'.\n", fullcmd);
02022    }
02023    AST_RWLIST_UNLOCK(&helpers);
02024    return res;
02025 }

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

Definition at line 245 of file cli.c.

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

00246 {
00247    /* "module load <mod>" */
00248    switch (cmd) {
00249    case CLI_INIT:
00250       e->command = "module load";
00251       e->usage =
00252          "Usage: module load <module name>\n"
00253          "       Loads the specified module into Asterisk.\n";
00254       return NULL;
00255 
00256    case CLI_GENERATE:
00257       if (a->pos != e->args)
00258          return NULL;
00259       return complete_fn(a->word, a->n);
00260    }
00261    if (a->argc != e->args + 1)
00262       return CLI_SHOWUSAGE;
00263    if (ast_load_resource(a->argv[e->args])) {
00264       ast_cli(a->fd, "Unable to load module %s\n", a->argv[e->args]);
00265       return CLI_FAILURE;
00266    }
00267    return CLI_SUCCESS;
00268 }

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

Definition at line 518 of file cli.c.

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

00519 {
00520    switch (cmd) {
00521    case CLI_INIT:
00522       e->command = "logger mute";
00523       e->usage = 
00524          "Usage: logger mute\n"
00525          "       Disables logging output to the current console, making it possible to\n"
00526          "       gather information without being disturbed by scrolling lines.\n";
00527       return NULL;
00528    case CLI_GENERATE:
00529       return NULL;
00530    }
00531 
00532    if (a->argc < 2 || a->argc > 3)
00533       return CLI_SHOWUSAGE;
00534 
00535    if (a->argc == 3 && !strcasecmp(a->argv[2], "silent"))
00536       ast_console_toggle_mute(a->fd, 1);
00537    else
00538       ast_console_toggle_mute(a->fd, 0);
00539 
00540    return CLI_SUCCESS;
00541 }

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

Definition at line 697 of file cli.c.

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

00698 {
00699    char *like;
00700 
00701    switch (cmd) {
00702    case CLI_INIT:
00703       e->command = "module show [like]";
00704       e->usage =
00705          "Usage: module show [like keyword]\n"
00706          "       Shows Asterisk modules currently in use, and usage statistics.\n";
00707       return NULL;
00708 
00709    case CLI_GENERATE:
00710       if (a->pos == e->args)
00711          return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);
00712       else
00713          return NULL;
00714    }
00715    /* all the above return, so we proceed with the handler.
00716     * we are guaranteed to have argc >= e->args
00717     */
00718    if (a->argc == e->args - 1)
00719       like = "";
00720    else if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args-1], "like") )
00721       like = a->argv[e->args];
00722    else
00723       return CLI_SHOWUSAGE;
00724       
00725    ast_mutex_lock(&climodentrylock);
00726    climodentryfd = a->fd; /* global, protected by climodentrylock */
00727    ast_cli(a->fd, MODLIST_FORMAT2, "Module", "Description", "Use Count");
00728    ast_cli(a->fd,"%d modules loaded\n", ast_update_module_list(modlist_modentry, like));
00729    climodentryfd = -1;
00730    ast_mutex_unlock(&climodentrylock);
00731    return CLI_SUCCESS;
00732 }

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

Definition at line 1251 of file cli.c.

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

01252 {
01253    char *res;
01254    if (cmd == CLI_HANDLER) {
01255       if (a->argc != e->args + 1)
01256          return CLI_SHOWUSAGE;
01257       /* pretend we have an extra "off" at the end. We can do this as the array
01258        * is NULL terminated so we overwrite that entry.
01259        */
01260       a->argv[e->args+1] = "off";
01261       a->argc++;
01262    }
01263    res = handle_core_set_debug_channel(e, cmd, a);
01264    if (cmd == CLI_INIT)
01265       e->command = "no debug channel";
01266    return res;
01267 }

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

Definition at line 270 of file cli.c.

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

00271 {
00272    int x;
00273 
00274    switch (cmd) {
00275    case CLI_INIT:
00276       e->command = "module reload";
00277       e->usage =
00278          "Usage: module reload [module ...]\n"
00279          "       Reloads configuration files for all listed modules which support\n"
00280          "       reloading, or for all supported modules if none are listed.\n";
00281       return NULL;
00282 
00283    case CLI_GENERATE:
00284       return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 1);
00285    }
00286    if (a->argc == e->args) {
00287       ast_module_reload(NULL);
00288       return CLI_SUCCESS;
00289    }
00290    for (x = e->args; x < a->argc; x++) {
00291       int res = ast_module_reload(a->argv[x]);
00292       /* XXX reload has multiple error returns, including -1 on error and 2 on success */
00293       switch (res) {
00294       case 0:
00295          ast_cli(a->fd, "No such module '%s'\n", a->argv[x]);
00296          break;
00297       case 1:
00298          ast_cli(a->fd, "Module '%s' does not support reload\n", a->argv[x]);
00299          break;
00300       }
00301    }
00302    return CLI_SUCCESS;
00303 }

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

Definition at line 736 of file cli.c.

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

00737 {
00738    struct timeval curtime = ast_tvnow();
00739    int showuptime, printsec;
00740 
00741    switch (cmd) {
00742    case CLI_INIT:
00743       e->command = "core show calls [uptime]";
00744       e->usage =
00745          "Usage: core show calls [uptime] [seconds]\n"
00746          "       Lists number of currently active calls and total number of calls\n"
00747          "       processed through PBX since last restart. If 'uptime' is specified\n"
00748          "       the system uptime is also displayed. If 'seconds' is specified in\n"
00749          "       addition to 'uptime', the system uptime is displayed in seconds.\n";
00750       return NULL;
00751 
00752    case CLI_GENERATE:
00753       if (a->pos != e->args)
00754          return NULL;
00755       return a->n == 0  ? ast_strdup("seconds") : NULL;
00756    }
00757 
00758    /* regular handler */
00759    if (a->argc >= e->args && !strcasecmp(a->argv[e->args-1],"uptime")) {
00760       showuptime = 1;
00761 
00762       if (a->argc == e->args+1 && !strcasecmp(a->argv[e->args],"seconds"))
00763          printsec = 1;
00764       else if (a->argc == e->args)
00765          printsec = 0;
00766       else
00767          return CLI_SHOWUSAGE;
00768    } else if (a->argc == e->args-1) {
00769       showuptime = 0;
00770       printsec = 0;
00771    } else
00772       return CLI_SHOWUSAGE;
00773 
00774    if (option_maxcalls) {
00775       ast_cli(a->fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
00776          ast_active_calls(), option_maxcalls, ESS(ast_active_calls()),
00777          ((double)ast_active_calls() / (double)option_maxcalls) * 100.0);
00778    } else {
00779       ast_cli(a->fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
00780    }
00781    
00782    ast_cli(a->fd, "%d call%s processed\n", ast_processed_calls(), ESS(ast_processed_calls()));
00783 
00784    if (ast_startuptime.tv_sec && showuptime) {
00785       print_uptimestr(a->fd, ast_tvsub(curtime, ast_startuptime), "System uptime", printsec);
00786    }
00787 
00788    return RESULT_SUCCESS;
00789 }

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

Definition at line 1269 of file cli.c.

References ast_channel::_bridge, ast_channel::_state, ast_channel::appl, ast_cli_args::argc, ast_cli_args::argv, ast_bridged_channel(), ast_cdr_serialize_variables(), ast_channel_unlock, ast_cli(), ast_complete_channels(), AST_FLAG_BLOCKING, ast_get_channel_by_name_locked(), ast_getformatname_multiple(), ast_state2str(), ast_str_buffer(), ast_str_thread_get(), ast_test_flag, ast_tvnow(), ast_channel::blockproc, ast_channel::callgroup, ast_channel::cdr, ast_channel::cid, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_channel::context, ast_channel::data, DEBUGCHAN_FLAG, ast_channel::exten, ast_cli_args::fd, ast_channel::fds, ast_channel::fin, ast_channel::fout, ast_channel::language, ast_cli_args::line, ast_cli_args::n, name, ast_channel::name, ast_channel::nativeformats, pbx_builtin_serialize_variables(), ast_channel::pickupgroup, ast_cli_args::pos, ast_channel::priority, ast_channel::readformat, ast_channel::readtrans, ast_channel::rings, S_OR, sec, ast_cdr::start, ast_channel::tech, ast_channel_tech::type, ast_channel::uniqueid, ast_cli_entry::usage, ast_channel::whentohangup, ast_cli_args::word, ast_channel::writeformat, and ast_channel::writetrans.

01270 {
01271    struct ast_channel *c=NULL;
01272    struct timeval now;
01273    struct ast_str *out = ast_str_thread_get(&ast_str_thread_global_buf, 16);
01274    char cdrtime[256];
01275    char nf[256], wf[256], rf[256];
01276    long elapsed_seconds=0;
01277    int hour=0, min=0, sec=0;
01278 #ifdef CHANNEL_TRACE
01279    int trace_enabled;
01280 #endif
01281 
01282    switch (cmd) {
01283    case CLI_INIT:
01284       e->command = "core show channel";
01285       e->usage = 
01286          "Usage: core show channel <channel>\n"
01287          "       Shows lots of information about the specified channel.\n";
01288       return NULL;
01289    case CLI_GENERATE:
01290       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
01291    }
01292    
01293    if (a->argc != 4)
01294       return CLI_SHOWUSAGE;
01295    now = ast_tvnow();
01296    c = ast_get_channel_by_name_locked(a->argv[3]);
01297    if (!c) {
01298       ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
01299       return CLI_SUCCESS;
01300    }
01301    if (c->cdr) {
01302       elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
01303       hour = elapsed_seconds / 3600;
01304       min = (elapsed_seconds % 3600) / 60;
01305       sec = elapsed_seconds % 60;
01306       snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
01307    } else
01308       strcpy(cdrtime, "N/A");
01309    ast_cli(a->fd, 
01310       " -- General --\n"
01311       "           Name: %s\n"
01312       "           Type: %s\n"
01313       "       UniqueID: %s\n"
01314       "      Caller ID: %s\n"
01315       " Caller ID Name: %s\n"
01316       "    DNID Digits: %s\n"
01317       "       Language: %s\n"
01318       "          State: %s (%d)\n"
01319       "          Rings: %d\n"
01320       "  NativeFormats: %s\n"
01321       "    WriteFormat: %s\n"
01322       "     ReadFormat: %s\n"
01323       " WriteTranscode: %s\n"
01324       "  ReadTranscode: %s\n"
01325       "1st File Descriptor: %d\n"
01326       "      Frames in: %d%s\n"
01327       "     Frames out: %d%s\n"
01328       " Time to Hangup: %ld\n"
01329       "   Elapsed Time: %s\n"
01330       "  Direct Bridge: %s\n"
01331       "Indirect Bridge: %s\n"
01332       " --   PBX   --\n"
01333       "        Context: %s\n"
01334       "      Extension: %s\n"
01335       "       Priority: %d\n"
01336       "     Call Group: %llu\n"
01337       "   Pickup Group: %llu\n"
01338       "    Application: %s\n"
01339       "           Data: %s\n"
01340       "    Blocking in: %s\n",
01341       c->name, c->tech->type, c->uniqueid,
01342       S_OR(c->cid.cid_num, "(N/A)"),
01343       S_OR(c->cid.cid_name, "(N/A)"),
01344       S_OR(c->cid.cid_dnid, "(N/A)"), 
01345       c->language,   
01346       ast_state2str(c->_state), c->_state, c->rings, 
01347       ast_getformatname_multiple(nf, sizeof(nf), c->nativeformats), 
01348       ast_getformatname_multiple(wf, sizeof(wf), c->writeformat), 
01349       ast_getformatname_multiple(rf, sizeof(rf), c->readformat),
01350       c->writetrans ? "Yes" : "No",
01351       c->readtrans ? "Yes" : "No",
01352       c->fds[0],
01353       c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
01354       c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
01355       (long)c->whentohangup.tv_sec,
01356       cdrtime, c->_bridge ? c->_bridge->name : "<none>", ast_bridged_channel(c) ? ast_bridged_channel(c)->name : "<none>", 
01357       c->context, c->exten, c->priority, c->callgroup, c->pickupgroup, ( c->appl ? c->appl : "(N/A)" ),
01358       ( c-> data ? S_OR(c->data, "(Empty)") : "(None)"),
01359       (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
01360    
01361    if (pbx_builtin_serialize_variables(c, &out))
01362       ast_cli(a->fd,"      Variables:\n%s\n", ast_str_buffer(out));
01363    if (c->cdr && ast_cdr_serialize_variables(c->cdr, &out, '=', '\n', 1))
01364       ast_cli(a->fd,"  CDR Variables:\n%s\n", ast_str_buffer(out));
01365 #ifdef CHANNEL_TRACE
01366    trace_enabled = ast_channel_trace_is_enabled(c);
01367    ast_cli(a->fd, "  Context Trace: %s\n", trace_enabled ? "Enabled" : "Disabled");
01368    if (trace_enabled && ast_channel_trace_serialize(c, &out))
01369       ast_cli(a->fd, "          Trace:\n%s\n", ast_str_buffer(out));
01370 #endif
01371    ast_channel_unlock(c);
01372    return CLI_SUCCESS;
01373 }

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

Definition at line 666 of file cli.c.

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

00667 {
00668    struct timeval curtime = ast_tvnow();
00669    int printsec;
00670 
00671    switch (cmd) {
00672    case CLI_INIT:
00673       e->command = "core show uptime [seconds]";
00674       e->usage =
00675          "Usage: core show uptime [seconds]\n"
00676          "       Shows Asterisk uptime information.\n"
00677          "       The seconds word returns the uptime in seconds only.\n";
00678       return NULL;
00679 
00680    case CLI_GENERATE:
00681       return NULL;
00682    }
00683    /* regular handler */
00684    if (a->argc == e->args && !strcasecmp(a->argv[e->args-1],"seconds"))
00685       printsec = 1;
00686    else if (a->argc == e->args-1)
00687       printsec = 0;
00688    else
00689       return CLI_SHOWUSAGE;
00690    if (ast_startuptime.tv_sec)
00691       print_uptimestr(a->fd, ast_tvsub(curtime, ast_startuptime), "System uptime", printsec);
00692    if (ast_lastreloadtime.tv_sec)
00693       print_uptimestr(a->fd, ast_tvsub(curtime, ast_lastreloadtime), "Last reload", printsec);
00694    return CLI_SUCCESS;
00695 }

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

Definition at line 913 of file cli.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_channel_unlock, ast_cli(), ast_complete_channels(), ast_get_channel_by_name_locked(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_channel::name, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

00914 {
00915    struct ast_channel *c=NULL;
00916 
00917    switch (cmd) {
00918    case CLI_INIT:
00919       e->command = "channel request hangup";
00920       e->usage =
00921          "Usage: channel request hangup <channel>\n"
00922          "       Request that a channel be hung up. The hangup takes effect\n"
00923          "       the next time the driver reads or writes from the channel\n";
00924       return NULL;
00925    case CLI_GENERATE:
00926       return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args);
00927    }
00928    if (a->argc != 4)
00929       return CLI_SHOWUSAGE;
00930    c = ast_get_channel_by_name_locked(a->argv[3]);
00931    if (c) {
00932       ast_cli(a->fd, "Requested Hangup on channel '%s'\n", c->name);
00933       ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
00934       ast_channel_unlock(c);
00935    } else
00936       ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
00937    return CLI_SUCCESS;
00938 }

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

Definition at line 543 of file cli.c.

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

00544 {
00545    /* "module unload mod_1 [mod_2 .. mod_N]" */
00546    int x;
00547    int force = AST_FORCE_SOFT;
00548    char *s;
00549 
00550    switch (cmd) {
00551    case CLI_INIT:
00552       e->command = "module unload";
00553       e->usage =
00554          "Usage: module unload [-f|-h] <module_1> [<module_2> ... ]\n"
00555          "       Unloads the specified module from Asterisk. The -f\n"
00556          "       option causes the module to be unloaded even if it is\n"
00557          "       in use (may cause a crash) and the -h module causes the\n"
00558          "       module to be unloaded even if the module says it cannot, \n"
00559          "       which almost always will cause a crash.\n";
00560       return NULL;
00561 
00562    case CLI_GENERATE:
00563       return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);
00564    }
00565    if (a->argc < e->args + 1)
00566       return CLI_SHOWUSAGE;
00567    x = e->args;   /* first argument */
00568    s = a->argv[x];
00569    if (s[0] == '-') {
00570       if (s[1] == 'f')
00571          force = AST_FORCE_FIRM;
00572       else if (s[1] == 'h')
00573          force = AST_FORCE_HARD;
00574       else
00575          return CLI_SHOWUSAGE;
00576       if (a->argc < e->args + 2) /* need at least one module name */
00577          return CLI_SHOWUSAGE;
00578       x++;  /* skip this argument */
00579    }
00580 
00581    for (; x < a->argc; x++) {
00582       if (ast_unload_resource(a->argv[x], force)) {
00583          ast_cli(a->fd, "Unable to unload resource %s\n", a->argv[x]);
00584          return CLI_FAILURE;
00585       }
00586    }
00587    return CLI_SUCCESS;
00588 }

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

Definition at line 362 of file cli.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_calloc, ast_clear_flag, ast_cli(), ast_complete_source_filename(), ast_free, AST_OPT_FLAG_DEBUG_FILE, AST_OPT_FLAG_VERBOSE_FILE, ast_options, AST_RWLIST_EMPTY, AST_RWLIST_INSERT_TAIL, AST_RWLIST_REMOVE, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_set_flag, ast_strdup, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_number(), debug, ast_cli_args::fd, ast_debug_file::filename, find_debug_file(), ast_debug_file::level, ast_cli_args::n, option_debug, option_verbose, ast_cli_args::pos, S_OR, and ast_cli_entry::usage.

00363 {
00364    int oldval;
00365    int newlevel;
00366    int atleast = 0;
00367    int fd = a->fd;
00368    int argc = a->argc;
00369    char **argv = a->argv;
00370    char *argv3 = a->argv ? S_OR(a->argv[3], "") : "";
00371    int *dst;
00372    char *what;
00373    struct debug_file_list *dfl;
00374    struct ast_debug_file *adf;
00375    char *fn;
00376 
00377    switch (cmd) {
00378    case CLI_INIT:
00379       e->command = "core set {debug|verbose}";
00380       e->usage =
00381 #if !defined(LOW_MEMORY)
00382          "Usage: core set {debug|verbose} [atleast] <level> [filename]\n"
00383 #else
00384          "Usage: core set {debug|verbose} [atleast] <level>\n"
00385 #endif
00386          "       core set {debug|verbose} off\n"
00387 #if !defined(LOW_MEMORY)
00388          "       Sets level of debug or verbose messages to be displayed or \n"
00389          "       sets a filename to display debug messages from.\n"
00390 #else
00391          "       Sets level of debug or verbose messages to be displayed.\n"
00392 #endif
00393          "  0 or off means no messages should be displayed.\n"
00394          "  Equivalent to -d[d[...]] or -v[v[v...]] on startup\n";
00395       return NULL;
00396 
00397    case CLI_GENERATE:
00398       if (a->pos == 3 || (a->pos == 4 && !strcasecmp(a->argv[3], "atleast"))) {
00399          char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], "");
00400          int numbermatch = (ast_strlen_zero(pos) || strchr("123456789", pos[0])) ? 0 : 21;
00401          if (a->n < 21 && numbermatch == 0) {
00402             return complete_number(pos, 0, 0x7fffffff, a->n);
00403          } else if (pos[0] == '0') {
00404             if (a->n == 0) {
00405                return ast_strdup("0");
00406             } else {
00407                return NULL;
00408             }
00409          } else if (a->n == (21 - numbermatch)) {
00410             if (a->pos == 3 && !strncasecmp(argv3, "off", strlen(argv3))) {
00411                return ast_strdup("off");
00412             } else if (a->pos == 3 && !strncasecmp(argv3, "atleast", strlen(argv3))) {
00413                return ast_strdup("atleast");
00414             }
00415          } else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) {
00416             return ast_strdup("atleast");
00417          }
00418 #if !defined(LOW_MEMORY)
00419       } else if (a->pos == 4 || (a->pos == 5 && !strcasecmp(argv3, "atleast"))) {
00420          return ast_complete_source_filename(a->pos == 4 ? S_OR(a->argv[4], "") : S_OR(a->argv[5], ""), a->n);
00421 #endif
00422       }
00423       return NULL;
00424    }
00425    /* all the above return, so we proceed with the handler.
00426     * we are guaranteed to be called with argc >= e->args;
00427     */
00428 
00429    if (argc <= e->args)
00430       return CLI_SHOWUSAGE;
00431    if (!strcasecmp(argv[e->args - 1], "debug")) {
00432       dst = &option_debug;
00433       oldval = option_debug;
00434       what = "Core debug";
00435    } else {
00436       dst = &option_verbose;
00437       oldval = option_verbose;
00438       what = "Verbosity";
00439    }
00440    if (argc == e->args + 1 && !strcasecmp(argv[e->args], "off")) {
00441       unsigned int debug = (*what == 'C');
00442       newlevel = 0;
00443 
00444       dfl = debug ? &debug_files : &verbose_files;
00445 
00446       AST_RWLIST_WRLOCK(dfl);
00447       while ((adf = AST_RWLIST_REMOVE_HEAD(dfl, entry)))
00448          ast_free(adf);
00449       ast_clear_flag(&ast_options, debug ? AST_OPT_FLAG_DEBUG_FILE : AST_OPT_FLAG_VERBOSE_FILE);
00450       AST_RWLIST_UNLOCK(dfl);
00451 
00452       goto done;
00453    }
00454    if (!strcasecmp(argv[e->args], "atleast"))
00455       atleast = 1;
00456    if (argc != e->args + atleast + 1 && argc != e->args + atleast + 2)
00457       return CLI_SHOWUSAGE;
00458    if (sscanf(argv[e->args + atleast], "%30d", &newlevel) != 1)
00459       return CLI_SHOWUSAGE;
00460    if (argc == e->args + atleast + 2) {
00461       unsigned int debug = (*what == 'C');
00462       dfl = debug ? &debug_files : &verbose_files;
00463 
00464       fn = argv[e->args + atleast + 1];
00465 
00466       AST_RWLIST_WRLOCK(dfl);
00467 
00468       if ((adf = find_debug_file(fn, debug)) && !newlevel) {
00469          AST_RWLIST_REMOVE(dfl, adf, entry);
00470          if (AST_RWLIST_EMPTY(dfl))
00471             ast_clear_flag(&ast_options, debug ? AST_OPT_FLAG_DEBUG_FILE : AST_OPT_FLAG_VERBOSE_FILE);
00472          AST_RWLIST_UNLOCK(dfl);
00473          ast_cli(fd, "%s was %d and has been set to 0 for '%s'\n", what, adf->level, fn);
00474          ast_free(adf);
00475          return CLI_SUCCESS;
00476       }
00477 
00478       if (adf) {
00479          if ((atleast && newlevel < adf->level) || adf->level == newlevel) {
00480             ast_cli(fd, "%s is %d for '%s'\n", what, adf->level, fn);
00481             AST_RWLIST_UNLOCK(dfl);
00482             return CLI_SUCCESS;
00483          }
00484       } else if (!(adf = ast_calloc(1, sizeof(*adf) + strlen(fn) + 1))) {
00485          AST_RWLIST_UNLOCK(dfl);
00486          return CLI_FAILURE;
00487       }
00488 
00489       oldval = adf->level;
00490       adf->level = newlevel;
00491       strcpy(adf->filename, fn);
00492 
00493       ast_set_flag(&ast_options, debug ? AST_OPT_FLAG_DEBUG_FILE : AST_OPT_FLAG_VERBOSE_FILE);
00494 
00495       AST_RWLIST_INSERT_TAIL(dfl, adf, entry);
00496       AST_RWLIST_UNLOCK(dfl);
00497 
00498       ast_cli(fd, "%s was %d and has been set to %d for '%s'\n", what, oldval, adf->level, adf->filename);
00499 
00500       return CLI_SUCCESS;
00501    }
00502 
00503 done:
00504    if (!atleast || newlevel > *dst)
00505       *dst = newlevel;
00506    if (oldval > 0 && *dst == 0)
00507       ast_cli(fd, "%s is now OFF\n", what);
00508    else if (*dst > 0) {
00509       if (oldval == *dst)
00510          ast_cli(fd, "%s is at least %d\n", what, *dst);
00511       else
00512          ast_cli(fd, "%s was %d and is now %d\n", what, oldval, *dst);
00513    }
00514 
00515    return CLI_SUCCESS;
00516 }

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

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

Definition at line 1952 of file cli.c.

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

Referenced by handle_help().

01953 {
01954    char matchstr[80] = "";
01955    struct ast_cli_entry *e = NULL;
01956    int len = 0;
01957    int found = 0;
01958 
01959    if (match) {
01960       ast_join(matchstr, sizeof(matchstr), match);
01961       len = strlen(matchstr);
01962    }
01963    if (!locked)
01964       AST_RWLIST_RDLOCK(&helpers);
01965    while ( (e = cli_next(e)) ) {
01966       /* Hide commands that start with '_' */
01967       if (e->_full_cmd[0] == '_')
01968          continue;
01969       if (match && strncasecmp(matchstr, e->_full_cmd, len))
01970          continue;
01971       ast_cli(fd, "%30.30s %s\n", e->_full_cmd, S_OR(e->summary, "<no description available>"));
01972       found++;
01973    }
01974    if (!locked)
01975       AST_RWLIST_UNLOCK(&helpers);
01976    if (!found && matchstr[0])
01977       ast_cli(fd, "No such command '%s'.\n", matchstr);
01978    return CLI_SUCCESS;
01979 }

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

References ast_strdup, ast_strlen_zero(), and s.

Referenced by __ast_cli_generator().

01725 {
01726    int lw;
01727    char *s, *t1;
01728 
01729    *actual = 0;
01730    if (ast_strlen_zero(token))
01731       return NULL;
01732    if (ast_strlen_zero(word))
01733       word = "";  /* dummy */
01734    lw = strlen(word);
01735    if (strcspn(word, cli_rsvd) != lw)
01736       return NULL;   /* no match if word has reserved chars */
01737    if (strchr(cli_rsvd, token[0]) == NULL) { /* regular match */
01738       if (strncasecmp(token, word, lw))   /* no match */
01739          return NULL;
01740       *actual = 1;
01741       return (pos != 0) ? NULL : ast_strdup(token);
01742    }
01743    /* now handle regexp match */
01744 
01745    /* Wildcard always matches, so we never do is_prefix on them */
01746 
01747    t1 = ast_strdupa(token + 1);  /* copy, skipping first char */
01748    while (pos >= 0 && (s = strsep(&t1, cli_rsvd)) && *s) {
01749       if (*s == '%') /* wildcard */
01750          continue;
01751       if (strncasecmp(s, word, lw)) /* no match */
01752          continue;
01753       (*actual)++;
01754       if (pos-- == 0)
01755          return ast_strdup(s);
01756    }
01757    return NULL;
01758 }

static int modlist_modentry ( const char *  module,
const char *  description,
int  usecnt,
const char *  like 
) [static]

Definition at line 596 of file cli.c.

References ast_cli(), and MODLIST_FORMAT.

Referenced by handle_modlist().

00597 {
00598    /* Comparing the like with the module */
00599    if (strcasestr(module, like) ) {
00600       ast_cli(climodentryfd, MODLIST_FORMAT, module, description, usecnt);
00601       return 1;
00602    } 
00603    return 0;
00604 }

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

returns true if there are more words to match

Definition at line 2158 of file cli.c.

Referenced by __ast_cli_generator().

02159 {
02160    int i;
02161    for (i = 0; dst[i]; i++) {
02162       if (dst[i][0] != '[')
02163          return -1;
02164    }
02165    return 0;
02166 }

static char* parse_args ( const char *  s,
int *  argc,
char *  argv[],
int  max,
int *  trailingwhitespace 
) [static]

Definition at line 2027 of file cli.c.

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

Referenced by __ast_cli_generator(), and ast_cli_command_full().

02028 {
02029    char *duplicate, *cur;
02030    int x = 0;
02031    int quoted = 0;
02032    int escaped = 0;
02033    int whitespace = 1;
02034    int dummy = 0;
02035 
02036    if (trailingwhitespace == NULL)
02037       trailingwhitespace = &dummy;
02038    *trailingwhitespace = 0;
02039    if (s == NULL) /* invalid, though! */
02040       return NULL;
02041    /* make a copy to store the parsed string */
02042    if (!(duplicate = ast_strdup(s)))
02043       return NULL;
02044 
02045    cur = duplicate;
02046    /* scan the original string copying into cur when needed */
02047    for (; *s ; s++) {
02048       if (x >= max - 1) {
02049          ast_log(LOG_WARNING, "Too many arguments, truncating at %s\n", s);
02050          break;
02051       }
02052       if (*s == '"' && !escaped) {
02053          quoted = !quoted;
02054          if (quoted && whitespace) {
02055             /* start a quoted string from previous whitespace: new argument */
02056             argv[x++] = cur;
02057             whitespace = 0;
02058          }
02059       } else if ((*s == ' ' || *s == '\t') && !(quoted || escaped)) {
02060          /* If we are not already in whitespace, and not in a quoted string or
02061             processing an escape sequence, and just entered whitespace, then
02062             finalize the previous argument and remember that we are in whitespace
02063          */
02064          if (!whitespace) {
02065             *cur++ = '\0';
02066             whitespace = 1;
02067          }
02068       } else if (*s == '\\' && !escaped) {
02069          escaped = 1;
02070       } else {
02071          if (whitespace) {
02072             /* we leave whitespace, and are not quoted. So it's a new argument */
02073             argv[x++] = cur;
02074             whitespace = 0;
02075          }
02076          *cur++ = *s;
02077          escaped = 0;
02078       }
02079    }
02080    /* Null terminate */
02081    *cur++ = '\0';
02082    /* XXX put a NULL in the last argument, because some functions that take
02083     * the array may want a null-terminated array.
02084     * argc still reflects the number of non-NULL entries.
02085     */
02086    argv[x] = NULL;
02087    *argc = x;
02088    *trailingwhitespace = whitespace;
02089    return duplicate;
02090 }

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

Definition at line 606 of file cli.c.

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

Referenced by handle_showcalls(), and handle_showuptime().

00607 {
00608    int x; /* the main part - years, weeks, etc. */
00609    struct ast_str *out;
00610 
00611 #define SECOND (1)
00612 #define MINUTE (SECOND*60)
00613 #define HOUR (MINUTE*60)
00614 #define DAY (HOUR*24)
00615 #define WEEK (DAY*7)
00616 #define YEAR (DAY*365)
00617 #define NEEDCOMMA(x) ((x)? ",": "") /* define if we need a comma */
00618    if (timeval.tv_sec < 0) /* invalid, nothing to show */
00619       return;
00620 
00621    if (printsec)  {  /* plain seconds output */
00622       ast_cli(fd, "%s: %lu\n", prefix, (u_long)timeval.tv_sec);
00623       return;
00624    }
00625    out = ast_str_alloca(256);
00626    if (timeval.tv_sec > YEAR) {
00627       x = (timeval.tv_sec / YEAR);
00628       timeval.tv_sec -= (x * YEAR);
00629       ast_str_append(&out, 0, "%d year%s%s ", x, ESS(x),NEEDCOMMA(timeval.tv_sec));
00630    }
00631    if (timeval.tv_sec > WEEK) {
00632       x = (timeval.tv_sec / WEEK);
00633       timeval.tv_sec -= (x * WEEK);
00634       ast_str_append(&out, 0, "%d week%s%s ", x, ESS(x),NEEDCOMMA(timeval.tv_sec));
00635    }
00636    if (timeval.tv_sec > DAY) {
00637       x = (timeval.tv_sec / DAY);
00638       timeval.tv_sec -= (x * DAY);
00639       ast_str_append(&out, 0, "%d day%s%s ", x, ESS(x),NEEDCOMMA(timeval.tv_sec));
00640    }
00641    if (timeval.tv_sec > HOUR) {
00642       x = (timeval.tv_sec / HOUR);
00643       timeval.tv_sec -= (x * HOUR);
00644       ast_str_append(&out, 0, "%d hour%s%s ", x, ESS(x),NEEDCOMMA(timeval.tv_sec));
00645    }
00646    if (timeval.tv_sec > MINUTE) {
00647       x = (timeval.tv_sec / MINUTE);
00648       timeval.tv_sec -= (x * MINUTE);
00649       ast_str_append(&out, 0, "%d minute%s%s ", x, ESS(x),NEEDCOMMA(timeval.tv_sec));
00650    }
00651    x = timeval.tv_sec;
00652    if (x > 0 || ast_str_strlen(out) == 0) /* if there is nothing, print 0 seconds */
00653       ast_str_append(&out, 0, "%d second%s ", x, ESS(x));
00654    ast_cli(fd, "%s: %s\n", prefix, ast_str_buffer(out));
00655 }

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 1520 of file cli.c.

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

Referenced by __ast_cli_register().

01521 {
01522    int i;
01523    char buf[80];
01524 
01525    ast_join(buf, sizeof(buf), e->cmda);
01526    e->_full_cmd = ast_strdup(buf);
01527    if (!e->_full_cmd) {
01528       ast_log(LOG_WARNING, "-- cannot allocate <%s>\n", buf);
01529       return -1;
01530    }
01531    e->cmdlen = strcspn(e->_full_cmd, cli_rsvd);
01532    for (i = 0; e->cmda[i]; i++)
01533       ;
01534    e->args = i;
01535    return 0;
01536 }

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 1694 of file cli.c.

References ast_strlen_zero().

Referenced by __ast_cli_generator(), and find_cli().

01695 {
01696    int l;
01697    char *pos;
01698 
01699    if (ast_strlen_zero(cmd) || ast_strlen_zero(cli_word))
01700       return -1;
01701    if (!strchr(cli_rsvd, cli_word[0])) /* normal match */
01702       return (strcasecmp(cmd, cli_word) == 0) ? 1 : -1;
01703    /* regexp match, takes [foo|bar] or {foo|bar} */
01704    l = strlen(cmd);
01705    /* wildcard match - will extend in the future */
01706    if (l > 0 && cli_word[0] == '%') {
01707       return 1;   /* wildcard */
01708    }
01709    pos = strcasestr(cli_word, cmd);
01710    if (pos == NULL) /* not found, say ok if optional */
01711       return cli_word[0] == '[' ? 0 : -1;
01712    if (pos == cli_word) /* no valid match at the beginning */
01713       return -1;
01714    if (strchr(cli_rsvd, pos[-1]) && strchr(cli_rsvd, pos[l]))
01715       return 1;   /* valid match */
01716    return -1;  /* not found */
01717 }


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 96 of file cli.c.

struct ast_cli_entry cli_cli[] [static]

Definition at line 1468 of file cli.c.

int cli_default_perm = 1 [static]

Default permissions value 1=Permit 0=Deny.

Definition at line 72 of file cli.c.

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

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

Definition at line 1514 of file cli.c.

int climodentryfd = -1 [static]

Definition at line 594 of file cli.c.

ast_mutex_t climodentrylock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 593 of file cli.c.

Referenced by handle_modlist().

struct debug_file_list debug_files [static]

list of filenames and their debug settings

Definition at line 92 of file cli.c.

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

CLI permissions config file.

Definition at line 70 of file cli.c.

Referenced by ast_cli_perms_init().

ast_mutex_t permsconfiglock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

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

Definition at line 76 of file cli.c.

struct debug_file_list verbose_files [static]

list of filenames and their verbose settings

Definition at line 94 of file cli.c.


Generated by  doxygen 1.6.2