Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:28 2007

Asterisk developer's documentation :: Codename Pineapple


cli.c File Reference


Detailed Description

Standard Command Line Interface.

Author:
Mark Spencer <markster@digium.com>

Definition in file cli.c.

#include "asterisk.h"
#include <unistd.h>
#include <stdlib.h>
#include <sys/signal.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <ctype.h>
#include <regex.h>
#include "asterisk/logger.h"
#include "asterisk/options.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 "editline/readline/readline.h"
#include "asterisk/threadstorage.h"

Include dependency graph for cli.c:

Go to the source code of this file.

Data Structures

struct  cli_iterator

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\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)
void ast_builtins_init (void)
 initialize the _full_cmd string in * each of the builtins.
void ast_cli (int fd, char *fmt,...)
int ast_cli_command (int fd, const char *s)
 Interprets a command Interpret a command s, sending output to fd Returns 0 on succes, -1 on failure.
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 Returns 0 on success, -1 on failure.
int ast_cli_generatornummatches (const char *text, const char *word)
 Return the number of unique matches for the generator.
int ast_cli_register (struct ast_cli_entry *e)
 Registers a command or an array of commands.
void 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.
void 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.
static AST_LIST_HEAD_STATIC (helpers, ast_cli_entry)
 AST_MUTEX_DEFINE_STATIC (climodentrylock)
 AST_THREADSTORAGE (ast_cli_buf)
static struct ast_cli_entrycli_next (struct cli_iterator *i)
static char * complete_ch_3 (const char *line, const char *word, int pos, int state)
static char * complete_ch_4 (const char *line, const char *word, int pos, int state)
static char * complete_fn (const char *word, int state)
static char * find_best (char *argv[])
static struct ast_cli_entryfind_cli (char *const cmds[], int match_type)
 locate a cli command in the 'helpers' list (which must be locked). exact has 3 values: 0 returns if the search key is equal or longer than the entry. note that trailing optional arguments are skipped. -1 true if the mismatch is on the last word XXX not true! 1 true only on complete, exact match.
static int group_show_channels (int fd, int argc, char *argv[])
static char * handle_chanlist (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int handle_commandcomplete (int fd, int argc, char *argv[])
static int handle_commandmatchesarray (int fd, int argc, char *argv[])
static int handle_commandnummatches (int fd, int argc, char *argv[])
static char * handle_core_set_debug_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_debugchan_deprecated (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_load_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int handle_logger_mute (int fd, int argc, char *argv[])
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_reload_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int handle_showchan (int fd, int argc, char *argv[])
static char * handle_showuptime (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int handle_softhangup (int fd, int argc, char *argv[])
static char * handle_unload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_unload_deprecated (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 = 0 it's just "help_workhorse", otherwise assume the list is already locked and print an error message if not found.
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, time_t 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_cli_entry builtins []
static struct ast_cli_entry cli_cli []
static struct ast_cli_entry cli_debug_channel_deprecated = NEW_CLI(handle_debugchan_deprecated, "Enable debugging on channel")
static struct ast_cli_entry cli_module_load_deprecated = NEW_CLI(handle_load_deprecated, "Load a module")
static struct ast_cli_entry cli_module_reload_deprecated = NEW_CLI(handle_reload_deprecated, "reload modules by name")
static struct ast_cli_entry cli_module_unload_deprecated = NEW_CLI(handle_unload_deprecated, "unload modules by name")
static const char cli_rsvd [] = "[]{}|*%"
static int climodentryfd = -1
static const char commandcomplete_help []
static const char commandmatchesarray_help []
static const char commandnummatches_help []
static const char group_show_channels_help []
static const char logger_mute_help []
static const char showchan_help []
static const char softhangup_help []


Define Documentation

#define AST_CLI_INITLEN   256
 

Initial buffer size for resulting strings in ast_cli().

Definition at line 55 of file cli.c.

Referenced by ast_cli().

#define CONCISE_FORMAT_STRING   "%s!%s!%s!%d!%s!%s!%s!%s!%s!%d!%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"
 

Referenced by group_show_channels(), and handle_chanlist().

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

Referenced by modlist_modentry().

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

Definition at line 315 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 1596 of file cli.c.

References ast_join(), AST_LIST_LOCK, AST_MAX_ARGS, ast_strlen_zero(), cli_next(), ast_cli_entry::cmda, free, cli_iterator::helpers, is_prefix(), more_words(), parse_args(), and word_match().

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

01597 {
01598    char *argv[AST_MAX_ARGS];
01599    struct ast_cli_entry *e;
01600    struct cli_iterator i = { NULL, NULL };
01601    int x = 0, argindex, matchlen;
01602    int matchnum=0;
01603    char *ret = NULL;
01604    char matchstr[80] = "";
01605    int tws = 0;
01606    /* Split the argument into an array of words */
01607    char *dup = parse_args(text, &x, argv, sizeof(argv) / sizeof(argv[0]), &tws);
01608 
01609    if (!dup)   /* malloc error */
01610       return NULL;
01611 
01612    /* Compute the index of the last argument (could be an empty string) */
01613    argindex = (!ast_strlen_zero(word) && x>0) ? x-1 : x;
01614 
01615    /* rebuild the command, ignore terminating white space and flatten space */
01616    ast_join(matchstr, sizeof(matchstr)-1, argv);
01617    matchlen = strlen(matchstr);
01618    if (tws) {
01619       strcat(matchstr, " "); /* XXX */
01620       if (matchlen)
01621          matchlen++;
01622    }
01623    if (lock)
01624       AST_LIST_LOCK(&helpers);
01625    while ( (e = cli_next(&i)) ) {
01626       /* XXX repeated code */
01627       int src = 0, dst = 0, n = 0;
01628 
01629       /*
01630        * Try to match words, up to and excluding the last word, which
01631        * is either a blank or something that we want to extend.
01632        */
01633       for (;src < argindex; dst++, src += n) {
01634          n = word_match(argv[src], e->cmda[dst]);
01635          if (n < 0)
01636             break;
01637       }
01638 
01639       if (src != argindex && more_words(e->cmda + dst))  /* not a match */
01640          continue;
01641       ret = is_prefix(argv[src], e->cmda[dst], state - matchnum, &n);
01642       matchnum += n; /* this many matches here */
01643       if (ret) {
01644          /*
01645           * argv[src] is a valid prefix of the next word in this
01646           * command. If this is also the correct entry, return it.
01647           */
01648          if (matchnum > state)
01649             break;
01650          free(ret);
01651          ret = NULL;
01652       } else if (ast_strlen_zero(e->cmda[dst])) {
01653          /*
01654           * This entry is a prefix of the command string entered
01655           * (only one entry in the list should have this property).
01656           * Run the generator if one is available. In any case we are done.
01657           */
01658          if (e->generator)
01659             ret = e->generator(matchstr, word, argindex, state - matchnum);
01660          else if (e->new_handler) { /* new style command */
01661             struct ast_cli_args a = {
01662                .line = matchstr, .word = word,
01663                .pos = argindex,
01664                .n = state - matchnum };
01665             ret = e->new_handler(e, CLI_GENERATE, &a);
01666          }
01667          if (ret)
01668             break;
01669       }
01670    }
01671    if (lock)
01672       AST_LIST_UNLOCK(&helpers);
01673    free(dup);
01674    return ret;
01675 }

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

Definition at line 1266 of file cli.c.

References AST_MAX_CMD_LEN, ast_strdup, ast_strlen_zero(), CLI_INIT, ast_cli_entry::cmda, ast_cli_entry::command, ast_cli_entry::handler, ast_cli_entry::new_handler, and s.

Referenced by ast_cli_register().

01267 {
01268    struct ast_cli_entry *cur;
01269    int i, lf, ret = -1;
01270 
01271    if (e->handler == NULL) {  /* new style entry, run the handler to init fields */
01272       struct ast_cli_args a;  /* fake argument */
01273       char **dst = (char **)e->cmda;   /* need to cast as the entry is readonly */
01274       char *s;
01275 
01276       bzero (&a, sizeof(a));
01277       e->new_handler(e, CLI_INIT, &a);
01278       /* XXX check that usage and command are filled up */
01279       s = ast_skip_blanks(e->command);
01280       s = e->command = ast_strdup(s);
01281       for (i=0; !ast_strlen_zero(s) && i < AST_MAX_CMD_LEN-1; i++) {
01282          *dst++ = s; /* store string */
01283          s = ast_skip_nonblanks(s);
01284          if (*s == '\0')   /* we are done */
01285             break;
01286          *s++ = '\0';
01287          s = ast_skip_blanks(s);
01288       }
01289       *dst++ = NULL;
01290    }
01291    if (set_full_cmd(e))
01292       goto done;
01293    AST_LIST_LOCK(&helpers);
01294    
01295    if (find_cli(e->cmda, 1)) {
01296       ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n", e->_full_cmd);
01297       free(e->_full_cmd);
01298       e->_full_cmd = NULL;
01299       goto done;
01300    }
01301    if (!ed) {
01302       e->deprecated = 0;
01303    } else {
01304       e->deprecated = 1;
01305       e->summary = ed->summary;
01306       e->usage = ed->usage;
01307       /* XXX If command A deprecates command B, and command B deprecates command C...
01308          Do we want to show command A or command B when telling the user to use new syntax?
01309          This currently would show command A.
01310          To show command B, you just need to always use ed->_full_cmd.
01311        */
01312       e->_deprecated_by = S_OR(ed->_deprecated_by, ed->_full_cmd);
01313    }
01314 
01315    lf = e->cmdlen;
01316    AST_LIST_TRAVERSE_SAFE_BEGIN(&helpers, cur, list) {
01317       int len = cur->cmdlen;
01318       if (lf < len)
01319          len = lf;
01320       if (strncasecmp(e->_full_cmd, cur->_full_cmd, len) < 0) {
01321          AST_LIST_INSERT_BEFORE_CURRENT(&helpers, e, list); 
01322          break;
01323       }
01324    }
01325    AST_LIST_TRAVERSE_SAFE_END;
01326 
01327    if (!cur)
01328       AST_LIST_INSERT_TAIL(&helpers, e, list); 
01329    ret = 0; /* success */
01330 
01331 done:
01332    AST_LIST_UNLOCK(&helpers);
01333 
01334    if (e->deprecate_cmd) {
01335       /* This command deprecates another command.  Register that one also. */
01336       __ast_cli_register(e->deprecate_cmd, e);
01337    }
01338    
01339    return ret;
01340 }

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

Definition at line 1242 of file cli.c.

References ast_cli_entry::_full_cmd, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), ast_cli_entry::cmda, ast_cli_entry::command, ast_cli_entry::deprecate_cmd, free, cli_iterator::helpers, ast_cli_entry::inuse, LOG_WARNING, ast_cli_entry::new_handler, and ast_cli_entry::usage.

Referenced by ast_cli_unregister().

01243 {
01244    if (e->deprecate_cmd) {
01245       __ast_cli_unregister(e->deprecate_cmd, e);
01246    }
01247    if (e->inuse) {
01248       ast_log(LOG_WARNING, "Can't remove command that is in use\n");
01249    } else {
01250       AST_LIST_LOCK(&helpers);
01251       AST_LIST_REMOVE(&helpers, e, list);
01252       AST_LIST_UNLOCK(&helpers);
01253       free(e->_full_cmd);
01254       e->_full_cmd = NULL;
01255       if (e->new_handler) {
01256          /* this is a new-style entry. Reset fields and free memory. */
01257          bzero((char **)(e->cmda), sizeof(e->cmda));
01258          free(e->command);
01259          e->command = NULL;
01260          e->usage = NULL;
01261       }
01262    }
01263    return 0;
01264 }

void ast_builtins_init void   ) 
 

initialize the _full_cmd string in * each of the builtins.

Provided by cli.c

Definition at line 1046 of file cli.c.

References ast_cli_register_multiple(), builtins, cli_cli, ast_cli_entry::cmda, and set_full_cmd().

01047 {
01048    struct ast_cli_entry *e;
01049 
01050    for (e = builtins; e->cmda[0] != NULL; e++)
01051       set_full_cmd(e);
01052 
01053    ast_cli_register_multiple(cli_cli, sizeof(cli_cli) / sizeof(struct ast_cli_entry));
01054 }

void ast_cli int  fd,
char *  fmt,
  ...
 

Definition at line 57 of file cli.c.

References ast_carefulwrite(), AST_CLI_INITLEN, ast_str_set_va, and ast_str::str.

Referenced by __iax2_show_peers(), __sip_show_channels(), _sip_show_device(), _sip_show_devices(), _sip_show_peer(), _sip_show_peers(), agent_logoff_cmd(), agents_show(), agents_show_online(), agi_do_debug(), agi_no_debug(), aji_do_reload(), aji_show_clients(), aji_test(), ast_cli_command(), ast_console_toggle_mute(), cli_audio_convert(), cli_files_show(), cli_realtime_load(), cli_realtime_update(), config_command(), console_active(), console_answer(), console_autoanswer(), console_dial(), console_flash(), console_hangup(), console_sendtext(), console_transfer(), database_del(), database_deltree(), database_get(), database_put(), database_show(), database_showkey(), do_boost(), dundi_do_debug(), dundi_do_lookup(), dundi_do_precache(), dundi_do_query(), dundi_do_store_history(), dundi_no_debug(), dundi_no_store_history(), dundi_show_entityid(), dundi_show_mappings(), dundi_show_peer(), dundi_show_peers(), dundi_show_precache(), dundi_show_requests(), dundi_show_trans(), features_show(), group_show_channels(), gtalk_show_channels(), h323_do_debug(), h323_do_trace(), h323_no_debug(), h323_no_trace(), handle_agidumphtml(), handle_chanlist(), handle_cli_status(), handle_cli_submit(), handle_commandcomplete(), handle_commandnummatches(), handle_context_add_extension(), handle_context_add_ignorepat(), handle_context_add_include(), handle_context_remove_extension(), handle_context_remove_ignorepat(), handle_context_remove_include(), handle_core_set_debug_channel(), handle_help(), handle_load(), handle_logger_reload(), handle_logger_rotate(), handle_logger_show_channels(), handle_mandebug(), handle_modlist(), handle_parkedcalls(), handle_reload(), handle_restart_when_convenient(), handle_save_dialplan(), handle_set_global(), handle_show_application(), handle_show_applications(), handle_show_dialplan(), handle_show_function(), handle_show_functions(), handle_show_globals(), handle_show_hints(), handle_show_http(), handle_show_indications(), handle_show_switches(), handle_show_threads(), handle_show_version_files(), handle_showagi(), handle_showchan(), handle_showfeatures(), handle_showmanager(), handle_showmanagers(), handle_showmancmd(), handle_showmancmds(), handle_showmanconn(), handle_showmaneventq(), handle_shutdown_when_convenient(), handle_softhangup(), handle_unload(), handle_verbose(), handle_version(), help1(), help_workhorse(), iax2_do_debug(), iax2_do_jb_debug(), iax2_do_trunk_debug(), iax2_no_debug(), iax2_no_jb_debug(), iax2_no_trunk_debug(), iax2_prov_cmd(), iax2_prune_realtime(), iax2_set_mtu(), iax2_show_cache(), iax2_show_channels(), iax2_show_firmware(), iax2_show_netstats(), iax2_show_peer(), iax2_show_registry(), iax2_show_stats(), iax2_show_threads(), iax2_show_users(), iax_show_provisioning(), locals_show(), mgcp_audit_endpoint(), mgcp_do_debug(), mgcp_no_debug(), mgcp_show_endpoints(), misdn_reload(), misdn_send_cd(), misdn_send_digit(), misdn_send_display(), misdn_set_debug(), misdn_show_cls(), misdn_show_config(), misdn_show_port(), misdn_show_ports_stats(), misdn_show_stacks(), misdn_toggle_echocancel(), modlist_modentry(), moh_classes_show(), moh_cli(), odbc_show_command(), orig_app(), orig_exten(), print_bc_info(), print_codec_to_cli(), print_group(), print_uptimestr(), realtime_pgsql_status(), rtcp_do_debug(), rtcp_do_debug_ip(), rtcp_do_stats(), rtcp_no_debug(), rtcp_no_stats(), rtp_do_debug(), rtp_do_debug_ip(), rtp_no_debug(), show_channeltype(), show_channeltypes(), show_codec_n(), show_codecs(), show_config_description(), show_dialplan_helper(), show_file_formats(), show_image_formats(), show_keys(), show_license(), show_translation(), show_warranty(), sip_do_debug(), sip_do_debug_device(), sip_do_debug_ip(), sip_do_debug_peer(), sip_do_history(), sip_listconfighelper(), sip_listconfigs(), sip_no_debug(), sip_no_history(), sip_notify(), sip_options_print(), sip_show_channel(), sip_show_domains(), sip_show_history(), sip_show_inuse(), sip_show_objects(), sip_show_registry(), sip_show_settings(), sip_show_user(), sip_show_users(), skinny_do_debug(), skinny_no_debug(), skinny_show_devices(), skinny_show_lines(), stun_do_debug(), stun_no_debug(), udptl_do_debug(), udptl_do_debug_ip(), udptl_nodebug(), and zap_show_status().

00058 {
00059    int res;
00060    struct ast_str *buf;
00061    va_list ap;
00062 
00063    if (!(buf = ast_str_thread_get(&ast_cli_buf, AST_CLI_INITLEN)))
00064       return;
00065 
00066    va_start(ap, fmt);
00067    res = ast_str_set_va(&buf, 0, fmt, ap);
00068    va_end(ap);
00069 
00070    if (res != AST_DYNSTR_BUILD_FAILED)
00071       ast_carefulwrite(fd, buf->str, strlen(buf->str), 100);
00072 }

int ast_cli_command int  fd,
const char *  s
 

Interprets a command Interpret a command s, sending output to fd Returns 0 on succes, -1 on failure.

Definition at line 1682 of file cli.c.

References ast_cli_entry::_deprecated_by, ast_cli_entry::_full_cmd, ast_cli(), AST_LIST_LOCK, AST_LIST_UNLOCK, AST_MAX_ARGS, CLI_HANDLER, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::deprecated, ast_cli_args::fd, find_best(), find_cli(), free, ast_cli_entry::handler, ast_cli_entry::inuse, ast_cli_entry::new_handler, parse_args(), RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, S_OR, and ast_cli_entry::usage.

Referenced by action_command(), cli_activate(), consolehandler(), and exit_completely().

01683 {
01684    char *args[AST_MAX_ARGS + 1];
01685    struct ast_cli_entry *e;
01686    int x;
01687    int res;
01688    char *dup = parse_args(s, &x, args + 1, AST_MAX_ARGS, NULL);
01689 
01690    if (dup == NULL)
01691       return -1;
01692 
01693    if (x < 1)  /* We need at least one entry, otherwise ignore */
01694       goto done;
01695 
01696    AST_LIST_LOCK(&helpers);
01697    e = find_cli(args + 1, 0);
01698    if (e)
01699       ast_atomic_fetchadd_int(&e->inuse, 1);
01700    AST_LIST_UNLOCK(&helpers);
01701    if (e == NULL) {
01702       ast_cli(fd, "No such command '%s' (type 'help' for help)\n", find_best(args + 1));
01703       goto done;
01704    }
01705    /*
01706     * Within the handler, argv[-1] contains a pointer to the ast_cli_entry.
01707     * Remember that the array returned by parse_args is NULL-terminated.
01708     */
01709    args[0] = (char *)e;
01710 
01711    if (!e->new_handler) /* old style */
01712       res = e->handler(fd, x, args + 1);
01713    else {
01714       struct ast_cli_args a = {
01715          .fd = fd, .argc = x, .argv = args+1 };
01716       char *retval = e->new_handler(e, CLI_HANDLER, &a);
01717 
01718       if (retval == CLI_SUCCESS)
01719          res = RESULT_SUCCESS;
01720       else if (retval == CLI_SHOWUSAGE)
01721          res = RESULT_SHOWUSAGE;
01722       else
01723          res = RESULT_FAILURE;
01724    }
01725    switch (res) {
01726    case RESULT_SHOWUSAGE:
01727       ast_cli(fd, "%s", S_OR(e->usage, "Invalid usage, but no usage information available.\n"));
01728       break;
01729 
01730    case RESULT_FAILURE:
01731       ast_cli(fd, "Command '%s' failed.\n", s);
01732       /* FALLTHROUGH */
01733    default:
01734       AST_LIST_LOCK(&helpers);
01735       if (e->deprecated == 1) {
01736          ast_cli(fd, "The '%s' command is deprecated and will be removed in a future release. Please use '%s' instead.\n", e->_full_cmd, e->_deprecated_by);
01737          e->deprecated = 2;
01738       }
01739       AST_LIST_UNLOCK(&helpers);
01740       break;
01741    }
01742    ast_atomic_fetchadd_int(&e->inuse, -1);
01743 done:
01744    free(dup);
01745    return 0;
01746 }

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

References ast_strdup, ast_strlen_zero(), and len.

Referenced by complete_orig(), and complete_show_applications().

00859 {
00860    int i, which = 0, len;
00861    len = ast_strlen_zero(word) ? 0 : strlen(word);
00862 
00863    for (i = 0; choices[i]; i++) {
00864       if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state)
00865          return ast_strdup(choices[i]);
00866    }
00867    return NULL;
00868 }

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, followe by a NULL. All strings and the array itself are malloc'ed and must be freed by the caller.

Definition at line 1535 of file cli.c.

References ast_cli_generator(), and ast_realloc.

Referenced by cli_complete(), and handle_commandmatchesarray().

01536 {
01537    char **match_list = NULL, *retstr, *prevstr;
01538    size_t match_list_len, max_equal, which, i;
01539    int matches = 0;
01540 
01541    /* leave entry 0 free for the longest common substring */
01542    match_list_len = 1;
01543    while ((retstr = ast_cli_generator(text, word, matches)) != NULL) {
01544       if (matches + 1 >= match_list_len) {
01545          match_list_len <<= 1;
01546          if (!(match_list = ast_realloc(match_list, match_list_len * sizeof(*match_list))))
01547             return NULL;
01548       }
01549       match_list[++matches] = retstr;
01550    }
01551 
01552    if (!match_list)
01553       return match_list; /* NULL */
01554 
01555    /* Find the longest substring that is common to all results
01556     * (it is a candidate for completion), and store a copy in entry 0.
01557     */
01558    prevstr = match_list[1];
01559    max_equal = strlen(prevstr);
01560    for (which = 2; which <= matches; which++) {
01561       for (i = 0; i < max_equal && toupper(prevstr[i]) == toupper(match_list[which][i]); i++)
01562          continue;
01563       max_equal = i;
01564    }
01565 
01566    if (!(retstr = ast_malloc(max_equal + 1)))
01567       return NULL;
01568    
01569    ast_copy_string(retstr, match_list[1], max_equal + 1);
01570    match_list[0] = retstr;
01571 
01572    /* ensure that the array is NULL terminated */
01573    if (matches + 1 >= match_list_len) {
01574       if (!(match_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(*match_list))))
01575          return NULL;
01576    }
01577    match_list[matches + 1] = NULL;
01578 
01579    return match_list;
01580 }

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

Readline madness Useful for readline, that's about it Returns 0 on success, -1 on failure.

Definition at line 1677 of file cli.c.

References __ast_cli_generator().

Referenced by ast_cli_completion_matches(), and ast_cli_generatornummatches().

01678 {
01679    return __ast_cli_generator(text, word, state, 1);
01680 }

int ast_cli_generatornummatches const char *  text,
const char *  word
 

Return the number of unique matches for the generator.

Definition at line 1518 of file cli.c.

References ast_cli_generator(), and free.

Referenced by handle_commandnummatches().

01519 {
01520    int matches = 0, i = 0;
01521    char *buf = NULL, *oldbuf = NULL;
01522 
01523    while ((buf = ast_cli_generator(text, word, i++))) {
01524       if (!oldbuf || strcmp(buf,oldbuf))
01525          matches++;
01526       if (oldbuf)
01527          free(oldbuf);
01528       oldbuf = buf;
01529    }
01530    if (oldbuf)
01531       free(oldbuf);
01532    return matches;
01533 }

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 Returns 0 on success, -1 on failure

Definition at line 1349 of file cli.c.

References __ast_cli_register().

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

01350 {
01351    return __ast_cli_register(e, NULL);
01352 }

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

References ast_cli_register().

Referenced by __ast_register_translator(), ast_builtins_init(), ast_channels_init(), ast_file_init(), ast_http_init(), ast_image_init(), ast_rtp_init(), ast_udptl_init(), astdb_init(), crypto_init(), iax_provision_init(), init_framer(), init_logger(), init_manager(), load_module(), load_pbx(), register_config_cli(), and sip_cli_and_manager_commands_register().

01358 {
01359    int i;
01360 
01361    for (i = 0; i < len; i++)
01362       ast_cli_register(e + i);
01363 }

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

References __ast_cli_unregister().

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

01344 {
01345    return __ast_cli_unregister(e, NULL);
01346 }

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

References ast_cli_unregister().

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

01366 {
01367    int i;
01368 
01369    for (i = 0; i < len; i++)
01370       ast_cli_unregister(e + i);
01371 }

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

References ast_channel_unlock, ast_channel_walk_locked(), and ast_strdup.

Referenced by complete_ch_3(), complete_ch_4(), and handle_core_set_debug_channel().

00871 {
00872    struct ast_channel *c = NULL;
00873    int which = 0;
00874    int wordlen;
00875    char notfound = '\0';
00876    char *ret = &notfound; /* so NULL can break the loop */
00877 
00878    if (pos != rpos)
00879       return NULL;
00880 
00881    wordlen = strlen(word); 
00882 
00883    while (ret == &notfound && (c = ast_channel_walk_locked(c))) {
00884       if (!strncasecmp(word, c->name, wordlen) && ++which > state)
00885          ret = ast_strdup(c->name);
00886       ast_channel_unlock(c);
00887    }
00888    return ret == &notfound ? NULL : ret;
00889 }

static AST_LIST_HEAD_STATIC helpers  ,
ast_cli_entry 
[static]
 

AST_MUTEX_DEFINE_STATIC climodentrylock   ) 
 

AST_THREADSTORAGE ast_cli_buf   ) 
 

static struct ast_cli_entry* cli_next struct cli_iterator i  )  [static]
 

Definition at line 1070 of file cli.c.

References ast_cli_entry::_full_cmd, AST_LIST_FIRST, AST_LIST_NEXT, builtins, cli_iterator::builtins, ast_cli_entry::cmda, and cli_iterator::helpers.

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

01071 {
01072    struct ast_cli_entry *e;
01073 
01074    if (i->builtins == NULL && i->helpers == NULL) {
01075       /* initialize */
01076       i->builtins = builtins;
01077       i->helpers = AST_LIST_FIRST(&helpers);
01078    }
01079    e = i->builtins; /* temporary */
01080    if (!e->cmda[0] || (i->helpers &&
01081           strcmp(i->helpers->_full_cmd, e->_full_cmd) < 0)) {
01082       /* Use helpers */
01083       e = i->helpers;
01084       if (e)
01085          i->helpers = AST_LIST_NEXT(e, list);
01086    } else { /* use builtin. e is already set  */
01087       (i->builtins)++;  /* move to next */
01088    }
01089    return e;
01090 }

static char* complete_ch_3 const char *  line,
const char *  word,
int  pos,
int  state
[static]
 

Definition at line 891 of file cli.c.

References ast_complete_channels().

00892 {
00893    return ast_complete_channels(line, word, pos, state, 2);
00894 }

static char* complete_ch_4 const char *  line,
const char *  word,
int  pos,
int  state
[static]
 

Definition at line 896 of file cli.c.

References ast_complete_channels().

00897 {
00898    return ast_complete_channels(line, word, pos, state, 3);
00899 }

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

Definition at line 92 of file cli.c.

References ast_config_AST_MODULE_DIR, and strdup.

Referenced by handle_load().

00093 {
00094    char *c;
00095    char filename[256];
00096 
00097    if (word[0] == '/')
00098       ast_copy_string(filename, word, sizeof(filename));
00099    else
00100       snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
00101 
00102    /* XXX the following function is not reentrant, so we better not use it */
00103    c = filename_completion_function(filename, state);
00104    
00105    if (c && word[0] != '/')
00106       c += (strlen(ast_config_AST_MODULE_DIR) + 1);
00107    
00108    return c ? strdup(c) : c;
00109 }

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

Definition at line 1223 of file cli.c.

References AST_LIST_LOCK, AST_MAX_CMD_LEN, find_cli(), and cli_iterator::helpers.

Referenced by ast_cli_command().

01224 {
01225    static char cmdline[80];
01226    int x;
01227    /* See how close we get, then print the candidate */
01228    char *myargv[AST_MAX_CMD_LEN];
01229    for (x=0;x<AST_MAX_CMD_LEN;x++)
01230       myargv[x]=NULL;
01231    AST_LIST_LOCK(&helpers);
01232    for (x=0;argv[x];x++) {
01233       myargv[x] = argv[x];
01234       if (!find_cli(myargv, -1))
01235          break;
01236    }
01237    AST_LIST_UNLOCK(&helpers);
01238    ast_join(cmdline, sizeof(cmdline), myargv);
01239    return cmdline;
01240 }

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

locate a cli command in the 'helpers' list (which must be locked). exact has 3 values: 0 returns if the search key is equal or longer than the entry. note that trailing optional arguments are skipped. -1 true if the mismatch is on the last word XXX not true! 1 true only on complete, exact match.

The search compares word by word taking care of regexps in e->cmda

Definition at line 1179 of file cli.c.

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

Referenced by ast_cli_command(), find_best(), and handle_help().

01180 {
01181    int matchlen = -1;   /* length of longest match so far */
01182    struct ast_cli_entry *cand = NULL, *e=NULL;
01183    struct cli_iterator i = { NULL, NULL};
01184 
01185    while ( (e = cli_next(&i)) ) {
01186       /* word-by word regexp comparison */
01187       char * const *src = cmds;
01188       char * const *dst = e->cmda;
01189       int n = 0;
01190       for (;; dst++, src += n) {
01191          n = word_match(*src, *dst);
01192          if (n < 0)
01193             break;
01194       }
01195       if (ast_strlen_zero(*dst) || ((*dst)[0] == '[' && ast_strlen_zero(dst[1]))) {
01196          /* no more words in 'e' */
01197          if (ast_strlen_zero(*src)) /* exact match, cannot do better */
01198             break;
01199          /* Here, cmds has more words than the entry 'e' */
01200          if (match_type != 0) /* but we look for almost exact match... */
01201             continue;   /* so we skip this one. */
01202          /* otherwise we like it (case 0) */
01203       } else { /* still words in 'e' */
01204          if (ast_strlen_zero(*src))
01205             continue; /* cmds is shorter than 'e', not good */
01206          /* Here we have leftover words in cmds and 'e',
01207           * but there is a mismatch. We only accept this one if match_type == -1
01208           * and this is the last word for both.
01209           */
01210          if (match_type != -1 || !ast_strlen_zero(src[1]) ||
01211              !ast_strlen_zero(dst[1])) /* not the one we look for */
01212             continue;
01213          /* good, we are in case match_type == -1 and mismatch on last word */
01214       }
01215       if (src - cmds > matchlen) {  /* remember the candidate */
01216          matchlen = src - cmds;
01217          cand = e;
01218       }
01219    }
01220    return e ? e : cand;
01221 }

static int group_show_channels int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 901 of file cli.c.

References ast_channel_unlock, ast_channel_walk_locked(), ast_cli(), AST_LIST_TRAVERSE, ast_var_name(), ast_var_value(), ESS, FORMAT_STRING, GROUP_CATEGORY_PREFIX, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ast_channel::varshead.

00902 {
00903 #define FORMAT_STRING  "%-25s  %-20s  %-20s\n"
00904 
00905    struct ast_channel *c = NULL;
00906    int numchans = 0;
00907    struct ast_var_t *current;
00908    struct varshead *headp;
00909    regex_t regexbuf;
00910    int havepattern = 0;
00911 
00912    if (argc < 3 || argc > 4)
00913       return RESULT_SHOWUSAGE;
00914    
00915    if (argc == 4) {
00916       if (regcomp(&regexbuf, argv[3], REG_EXTENDED | REG_NOSUB))
00917          return RESULT_SHOWUSAGE;
00918       havepattern = 1;
00919    }
00920 
00921    ast_cli(fd, FORMAT_STRING, "Channel", "Group", "Category");
00922    while ( (c = ast_channel_walk_locked(c)) != NULL) {
00923       headp=&c->varshead;
00924       AST_LIST_TRAVERSE(headp,current,entries) {
00925          if (!strncmp(ast_var_name(current), GROUP_CATEGORY_PREFIX "_", strlen(GROUP_CATEGORY_PREFIX) + 1)) {
00926             if (!havepattern || !regexec(&regexbuf, ast_var_value(current), 0, NULL, 0)) {
00927                ast_cli(fd, FORMAT_STRING, c->name, ast_var_value(current),
00928                   (ast_var_name(current) + strlen(GROUP_CATEGORY_PREFIX) + 1));
00929                numchans++;
00930             }
00931          } else if (!strcmp(ast_var_name(current), GROUP_CATEGORY_PREFIX)) {
00932             if (!havepattern || !regexec(&regexbuf, ast_var_value(current), 0, NULL, 0)) {
00933                ast_cli(fd, FORMAT_STRING, c->name, ast_var_value(current), "(default)");
00934                numchans++;
00935             }
00936          }
00937       }
00938       numchans++;
00939       ast_channel_unlock(c);
00940    }
00941 
00942    if (havepattern)
00943       regfree(&regexbuf);
00944 
00945    ast_cli(fd, "%d active channel%s\n", numchans, ESS(numchans));
00946    return RESULT_SUCCESS;
00947 #undef FORMAT_STRING
00948 }

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

Definition at line 452 of file cli.c.

References ast_channel::_state, 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_state2str(), ast_strlen_zero(), 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, option_maxcalls, ast_channel::priority, S_OR, ast_cdr::start, ast_cli_entry::usage, VERBOSE_FORMAT_STRING, and VERBOSE_FORMAT_STRING2.

00453 {
00454 #define FORMAT_STRING  "%-20.20s %-20.20s %-7.7s %-30.30s\n"
00455 #define FORMAT_STRING2 "%-20.20s %-20.20s %-7.7s %-30.30s\n"
00456 #define CONCISE_FORMAT_STRING  "%s!%s!%s!%d!%s!%s!%s!%s!%s!%d!%s!%s\n"
00457 #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"
00458 #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"
00459 
00460    struct ast_channel *c = NULL;
00461    int numchans = 0, concise = 0, verbose = 0, count = 0;
00462    int fd, argc;
00463    char **argv;
00464 
00465    switch (cmd) {
00466    case CLI_INIT:
00467       e->command = "core show channels [concise|verbose|count]";
00468       e->usage =
00469          "Usage: core show channels [concise|verbose|count]\n"
00470          "       Lists currently defined channels and some information about them. If\n"
00471          "       'concise' is specified, the format is abridged and in a more easily\n"
00472          "       machine parsable format. If 'verbose' is specified, the output includes\n"
00473          "       more and longer fields. If 'count' is specified only the channel and call\n"
00474          "       count is output.\n";
00475       return NULL;
00476 
00477    case CLI_GENERATE:
00478       return NULL;
00479    }
00480    fd = a->fd;
00481    argc = a->argc;
00482    argv = a->argv;
00483 
00484    if (a->argc == e->args) {
00485       if (!strcasecmp(argv[e->args-1],"concise"))
00486          concise = 1;
00487       else if (!strcasecmp(argv[e->args-1],"verbose"))
00488          verbose = 1;
00489       else if (!strcasecmp(argv[e->args-1],"count"))
00490          count = 1;
00491       else
00492          return CLI_SHOWUSAGE;
00493    } else if (a->argc != e->args - 1)
00494       return CLI_SHOWUSAGE;
00495 
00496    if (!count) {
00497       if (!concise && !verbose)
00498          ast_cli(fd, FORMAT_STRING2, "Channel", "Location", "State", "Application(Data)");
00499       else if (verbose)
00500          ast_cli(fd, VERBOSE_FORMAT_STRING2, "Channel", "Context", "Extension", "Priority", "State", "Application", "Data", 
00501             "CallerID", "Duration", "Accountcode", "BridgedTo");
00502    }
00503 
00504    while ((c = ast_channel_walk_locked(c)) != NULL) {
00505       struct ast_channel *bc = ast_bridged_channel(c);
00506       char durbuf[10] = "-";
00507 
00508       if (!count) {
00509          if ((concise || verbose)  && c->cdr && !ast_tvzero(c->cdr->start)) {
00510             int duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
00511             if (verbose) {
00512                int durh = duration / 3600;
00513                int durm = (duration % 3600) / 60;
00514                int durs = duration % 60;
00515                snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
00516             } else {
00517                snprintf(durbuf, sizeof(durbuf), "%d", duration);
00518             }           
00519          }
00520          if (concise) {
00521             ast_cli(fd, CONCISE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
00522                c->appl ? c->appl : "(None)",
00523                S_OR(c->data, ""),   /* XXX different from verbose ? */
00524                S_OR(c->cid.cid_num, ""),
00525                S_OR(c->accountcode, ""),
00526                c->amaflags, 
00527                durbuf,
00528                bc ? bc->name : "(None)");
00529          } else if (verbose) {
00530             ast_cli(fd, VERBOSE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
00531                c->appl ? c->appl : "(None)",
00532                c->data ? S_OR(c->data, "(Empty)" ): "(None)",
00533                S_OR(c->cid.cid_num, ""),
00534                durbuf,
00535                S_OR(c->accountcode, ""),
00536                bc ? bc->name : "(None)");
00537          } else {
00538             char locbuf[40] = "(None)";
00539             char appdata[40] = "(None)";
00540             
00541             if (!ast_strlen_zero(c->context) && !ast_strlen_zero(c->exten)) 
00542                snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", c->exten, c->context, c->priority);
00543             if (c->appl)
00544                snprintf(appdata, sizeof(appdata), "%s(%s)", c->appl, S_OR(c->data, ""));
00545             ast_cli(fd, FORMAT_STRING, c->name, locbuf, ast_state2str(c->_state), appdata);
00546          }
00547       }
00548       numchans++;
00549       ast_channel_unlock(c);
00550    }
00551    if (!concise) {
00552       ast_cli(fd, "%d active channel%s\n", numchans, ESS(numchans));
00553       if (option_maxcalls)
00554          ast_cli(fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
00555             ast_active_calls(), option_maxcalls, ESS(ast_active_calls()),
00556             ((double)ast_active_calls() / (double)option_maxcalls) * 100.0);
00557       else
00558          ast_cli(fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
00559    }
00560    return CLI_SUCCESS;
00561    
00562 #undef FORMAT_STRING
00563 #undef FORMAT_STRING2
00564 #undef CONCISE_FORMAT_STRING
00565 #undef VERBOSE_FORMAT_STRING
00566 #undef VERBOSE_FORMAT_STRING2
00567 }

static int handle_commandcomplete int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 662 of file cli.c.

References __ast_cli_generator(), ast_cli(), free, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00663 {
00664    char *buf;
00665 
00666    if (argc != 5)
00667       return RESULT_SHOWUSAGE;
00668    buf = __ast_cli_generator(argv[2], argv[3], atoi(argv[4]), 0);
00669    if (buf) {
00670       ast_cli(fd, buf);
00671       free(buf);
00672    } else
00673       ast_cli(fd, "NULL\n");
00674    return RESULT_SUCCESS;
00675 }

static int handle_commandmatchesarray int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 605 of file cli.c.

References ast_cli_completion_matches(), ast_malloc, ast_realloc, free, len, RESULT_FAILURE, and RESULT_SHOWUSAGE.

00606 {
00607    char *buf, *obuf;
00608    int buflen = 2048;
00609    int len = 0;
00610    char **matches;
00611    int x, matchlen;
00612 
00613    if (argc != 4)
00614       return RESULT_SHOWUSAGE;
00615    if (!(buf = ast_malloc(buflen)))
00616       return RESULT_FAILURE;
00617    buf[len] = '\0';
00618    matches = ast_cli_completion_matches(argv[2], argv[3]);
00619    if (matches) {
00620       for (x=0; matches[x]; x++) {
00621          matchlen = strlen(matches[x]) + 1;
00622          if (len + matchlen >= buflen) {
00623             buflen += matchlen * 3;
00624             obuf = buf;
00625             if (!(buf = ast_realloc(obuf, buflen))) 
00626                /* Memory allocation failure...  Just free old buffer and be done */
00627                free(obuf);
00628          }
00629          if (buf)
00630             len += sprintf( buf + len, "%s ", matches[x]);
00631          free(matches[x]);
00632          matches[x] = NULL;
00633       }
00634       free(matches);
00635    }
00636 
00637    if (buf) {
00638       ast_cli(fd, "%s%s",buf, AST_CLI_COMPLETE_EOF);
00639       free(buf);
00640    } else
00641       ast_cli(fd, "NULL\n");
00642 
00643    return RESULT_SUCCESS;
00644 }

static int handle_commandnummatches int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 648 of file cli.c.

References ast_cli(), ast_cli_generatornummatches(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00649 {
00650    int matches = 0;
00651 
00652    if (argc != 4)
00653       return RESULT_SHOWUSAGE;
00654 
00655    matches = ast_cli_generatornummatches(argv[2], argv[3]);
00656 
00657    ast_cli(fd, "%d", matches);
00658 
00659    return RESULT_SUCCESS;
00660 }

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

Definition at line 677 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(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, 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_cli_args::pos, RESULT_SUCCESS, strdup, ast_cli_entry::usage, and ast_cli_args::word.

Referenced by handle_debugchan_deprecated(), and handle_nodebugchan_deprecated().

00678 {
00679    struct ast_channel *c = NULL;
00680    int is_all, is_off = 0;
00681 
00682    switch (cmd) {
00683    case CLI_INIT:
00684       e->command = "core set debug channel";
00685       e->usage =
00686          "Usage: core set debug channel <all|channel> [off]\n"
00687          "       Enables/disables debugging on all or on a specific channel.\n";
00688       return NULL;
00689 
00690    case CLI_GENERATE:
00691       /* XXX remember to handle the optional "off" */
00692       if (a->pos != e->args)
00693          return NULL;
00694       return a->n == 0 ? strdup("all") : ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
00695    }
00696    /* 'core set debug channel {all|chan_id}' */
00697    if (a->argc == e->args + 2) {
00698       if (!strcasecmp(a->argv[e->args + 1], "off"))
00699          is_off = 1;
00700       else
00701          return CLI_SHOWUSAGE;
00702    } else if (a->argc != e->args + 1)
00703       return CLI_SHOWUSAGE;
00704 
00705    is_all = !strcasecmp("all", a->argv[e->args]);
00706    if (is_all) {
00707       if (is_off) {
00708          global_fin &= ~DEBUGCHAN_FLAG;
00709          global_fout &= ~DEBUGCHAN_FLAG;
00710       } else {
00711          global_fin |= DEBUGCHAN_FLAG;
00712          global_fout |= DEBUGCHAN_FLAG;
00713       }
00714       c = ast_channel_walk_locked(NULL);
00715    } else {
00716       c = ast_get_channel_by_name_locked(a->argv[e->args]);
00717       if (c == NULL)
00718          ast_cli(a->fd, "No such channel %s\n", a->argv[e->args]);
00719    }
00720    while (c) {
00721       if (!(c->fin & DEBUGCHAN_FLAG) || !(c->fout & DEBUGCHAN_FLAG)) {
00722          if (is_off) {
00723             c->fin &= ~DEBUGCHAN_FLAG;
00724             c->fout &= ~DEBUGCHAN_FLAG;
00725          } else {
00726             c->fin |= DEBUGCHAN_FLAG;
00727             c->fout |= DEBUGCHAN_FLAG;
00728          }
00729          ast_cli(a->fd, "Debugging %s on channel %s\n", is_off ? "disabled" : "enabled", c->name);
00730       }
00731       ast_channel_unlock(c);
00732       if (!is_all)
00733          break;
00734       c = ast_channel_walk_locked(c);
00735    }
00736    ast_cli(a->fd, "Debugging on new channels is %s\n", is_off ? "disabled" : "enabled");
00737    return RESULT_SUCCESS;
00738 }

static char* handle_debugchan_deprecated struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a
[static]
 

Definition at line 740 of file cli.c.

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

00741 {
00742    char *res;
00743 
00744    if (cmd == CLI_HANDLER && a->argc != e->args + 1)
00745       return CLI_SHOWUSAGE;
00746    res = handle_core_set_debug_channel(e, cmd, a);
00747    if (cmd == CLI_INIT)
00748       e->command = "debug channel";
00749    return res;
00750 }

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

Definition at line 1412 of file cli.c.

References __ast_cli_generator(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_join(), AST_LIST_LOCK, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, ast_cli_args::fd, find_cli(), help1(), ast_cli_args::line, ast_cli_args::n, RESULT_SUCCESS, ast_cli_entry::usage, and ast_cli_args::word.

01413 {
01414    char fullcmd[80];
01415    struct ast_cli_entry *my_e;
01416 
01417    if (cmd == CLI_INIT) {
01418       e->command = "help";
01419       e->usage =
01420          "Usage: help [topic]\n"
01421          "       When called with a topic as an argument, displays usage\n"
01422          "       information on the given command. If called without a\n"
01423          "       topic, it provides a list of commands.\n";
01424       return NULL;
01425 
01426    } else if (cmd == CLI_GENERATE) {
01427       /* skip first 4 or 5 chars, "help " */
01428       int l = strlen(a->line);
01429 
01430       if (l > 5)
01431          l = 5;
01432       /* XXX watch out, should stop to the non-generator parts */
01433       return __ast_cli_generator(a->line + l, a->word, a->n, 0);
01434    }
01435    if (a->argc == 1)
01436       return help1(a->fd, NULL, 0);
01437 
01438    AST_LIST_LOCK(&helpers);
01439    my_e = find_cli(a->argv + 1, 1); /* try exact match first */
01440    if (!my_e)
01441       return help1(a->fd, a->argv + 1, 1 /* locked */);
01442    if (my_e->usage)
01443       ast_cli(a->fd, "%s", my_e->usage);
01444    else {
01445       ast_join(fullcmd, sizeof(fullcmd), a->argv+1);
01446       ast_cli(a->fd, "No help text available for '%s'.\n", fullcmd);
01447    }
01448    AST_LIST_UNLOCK(&helpers);
01449    return RESULT_SUCCESS;
01450 }

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

Definition at line 111 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.

Referenced by handle_load_deprecated().

00112 {
00113    /* "module load <mod>" */
00114    switch (cmd) {
00115    case CLI_INIT:
00116       e->command = "module load";
00117       e->usage =
00118          "Usage: module load <module name>\n"
00119          "       Loads the specified module into Asterisk.\n";
00120       return NULL;
00121 
00122    case CLI_GENERATE:
00123       if (a->pos != e->args)
00124          return NULL;
00125       return complete_fn(a->word, a->n);
00126    }
00127    if (a->argc != e->args + 1)
00128       return CLI_SHOWUSAGE;
00129    if (ast_load_resource(a->argv[e->args])) {
00130       ast_cli(a->fd, "Unable to load module %s\n", a->argv[e->args]);
00131       return CLI_FAILURE;
00132    }
00133    return CLI_SUCCESS;
00134 }

static char* handle_load_deprecated struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a
[static]
 

Definition at line 136 of file cli.c.

References CLI_INIT, ast_cli_entry::command, and handle_load().

00137 {
00138    char *res = handle_load(e, cmd, a);
00139    if (cmd == CLI_INIT)
00140       e->command = "load";
00141    return res;
00142 }

static int handle_logger_mute int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 251 of file cli.c.

References ast_console_toggle_mute(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00252 {
00253    if (argc != 2)
00254       return RESULT_SHOWUSAGE;
00255    ast_console_toggle_mute(fd);
00256    return RESULT_SUCCESS;
00257 }

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

Definition at line 413 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, climodentryfd, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, MODLIST_FORMAT2, modlist_modentry(), ast_cli_args::n, ast_cli_args::pos, RESULT_SUCCESS, ast_cli_entry::usage, and ast_cli_args::word.

00414 {
00415    char *like;
00416 
00417    switch (cmd) {
00418    case CLI_INIT:
00419       e->command = "module show [like]";
00420       e->usage =
00421          "Usage: module show [like keyword]\n"
00422          "       Shows Asterisk modules currently in use, and usage statistics.\n";
00423       return NULL;
00424 
00425    case CLI_GENERATE:
00426       if (a->pos == e->args)
00427          return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);
00428       else
00429          return NULL;
00430    }
00431    /* all the above return, so we proceed with the handler.
00432     * we are guaranteed to have argc >= e->args
00433     */
00434    if (a->argc == e->args - 1)
00435       like = "";
00436    else if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args-1], "like") )
00437       like = a->argv[e->args];
00438    else
00439       return CLI_SHOWUSAGE;
00440       
00441    ast_mutex_lock(&climodentrylock);
00442    climodentryfd = a->fd; /* global, protected by climodentrylock */
00443    ast_cli(a->fd, MODLIST_FORMAT2, "Module", "Description", "Use Count");
00444    ast_cli(a->fd,"%d modules loaded\n", ast_update_module_list(modlist_modentry, like));
00445    climodentryfd = -1;
00446    ast_mutex_unlock(&climodentrylock);
00447    return RESULT_SUCCESS;
00448 }

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

Definition at line 752 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().

00753 {
00754    char *res;
00755    if (cmd == CLI_HANDLER) {
00756       if (a->argc != e->args + 1)
00757          return CLI_SHOWUSAGE;
00758       /* pretend we have an extra "off" at the end. We can do this as the array
00759        * is NULL terminated so we overwrite that entry.
00760        */
00761       a->argv[e->args+1] = "off";
00762       a->argc++;
00763    }
00764    res = handle_core_set_debug_channel(e, cmd, a);
00765    if (cmd == CLI_INIT)
00766       e->command = "no debug channel";
00767    return res;
00768 }

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

Definition at line 144 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.

Referenced by handle_reload_deprecated().

00145 {
00146    int x;
00147 
00148    switch (cmd) {
00149    case CLI_INIT:
00150       e->command = "module reload";
00151       e->usage =
00152          "Usage: module reload [module ...]\n"
00153          "       Reloads configuration files for all listed modules which support\n"
00154          "       reloading, or for all supported modules if none are listed.\n";
00155       return NULL;
00156 
00157    case CLI_GENERATE:
00158       return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 1);
00159    }
00160    if (a->argc == e->args) {
00161       ast_module_reload(NULL);
00162       return CLI_SUCCESS;
00163    }
00164    for (x = e->args; x < a->argc; x++) {
00165       int res = ast_module_reload(a->argv[x]);
00166       /* XXX reload has multiple error returns, including -1 on error and 2 on success */
00167       switch (res) {
00168       case 0:
00169          ast_cli(a->fd, "No such module '%s'\n", a->argv[x]);
00170          break;
00171       case 1:
00172          ast_cli(a->fd, "Module '%s' does not support reload\n", a->argv[x]);
00173          break;
00174       }
00175    }
00176    return CLI_SUCCESS;
00177 }

static char* handle_reload_deprecated struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a
[static]
 

Definition at line 179 of file cli.c.

References CLI_INIT, ast_cli_entry::command, handle_reload(), and s.

00180 {
00181    char *s = handle_reload(e, cmd, a);
00182    if (cmd == CLI_INIT)    /* override command name */
00183       e->command = "reload";
00184    return s;
00185 }

static int handle_showchan int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 770 of file cli.c.

References ast_channel::_bridge, ast_channel::_state, ast_bridged_channel(), ast_cdr_serialize_variables(), ast_channel_unlock, ast_cli(), AST_FLAG_BLOCKING, ast_get_channel_by_name_locked(), ast_getformatname_multiple(), ast_state2str(), ast_str_alloca, ast_test_flag, ast_channel::cdr, ast_channel::cid, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, DEBUGCHAN_FLAG, ast_channel::fds, ast_channel::fin, ast_channel::fout, name, ast_channel::nativeformats, pbx_builtin_serialize_variables(), ast_channel::readformat, ast_channel::readtrans, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_channel::rings, S_OR, ast_cdr::start, ast_str::str, ast_channel::tech, ast_channel_tech::type, ast_channel::whentohangup, ast_channel::writeformat, and ast_channel::writetrans.

00771 {
00772    struct ast_channel *c=NULL;
00773    struct timeval now;
00774    struct ast_str *out = ast_str_alloca(2048);
00775    char cdrtime[256];
00776    char nf[256], wf[256], rf[256];
00777    long elapsed_seconds=0;
00778    int hour=0, min=0, sec=0;
00779    
00780    if (argc != 4)
00781       return RESULT_SHOWUSAGE;
00782    now = ast_tvnow();
00783    c = ast_get_channel_by_name_locked(argv[3]);
00784    if (!c) {
00785       ast_cli(fd, "%s is not a known channel\n", argv[3]);
00786       return RESULT_SUCCESS;
00787    }
00788    if (c->cdr) {
00789       elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
00790       hour = elapsed_seconds / 3600;
00791       min = (elapsed_seconds % 3600) / 60;
00792       sec = elapsed_seconds % 60;
00793       snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
00794    } else
00795       strcpy(cdrtime, "N/A");
00796    ast_cli(fd, 
00797       " -- General --\n"
00798       "           Name: %s\n"
00799       "           Type: %s\n"
00800       "       UniqueID: %s\n"
00801       "      Caller ID: %s\n"
00802       " Caller ID Name: %s\n"
00803       "    DNID Digits: %s\n"
00804       "          State: %s (%d)\n"
00805       "          Rings: %d\n"
00806       "  NativeFormats: %s\n"
00807       "    WriteFormat: %s\n"
00808       "     ReadFormat: %s\n"
00809       " WriteTranscode: %s\n"
00810       "  ReadTranscode: %s\n"
00811       "1st File Descriptor: %d\n"
00812       "      Frames in: %d%s\n"
00813       "     Frames out: %d%s\n"
00814       " Time to Hangup: %ld\n"
00815       "   Elapsed Time: %s\n"
00816       "  Direct Bridge: %s\n"
00817       "Indirect Bridge: %s\n"
00818       " --   PBX   --\n"
00819       "        Context: %s\n"
00820       "      Extension: %s\n"
00821       "       Priority: %d\n"
00822       "     Call Group: %llu\n"
00823       "   Pickup Group: %llu\n"
00824       "    Application: %s\n"
00825       "           Data: %s\n"
00826       "    Blocking in: %s\n",
00827       c->name, c->tech->type, c->uniqueid,
00828       S_OR(c->cid.cid_num, "(N/A)"),
00829       S_OR(c->cid.cid_name, "(N/A)"),
00830       S_OR(c->cid.cid_dnid, "(N/A)"), ast_state2str(c->_state), c->_state, c->rings, 
00831       ast_getformatname_multiple(nf, sizeof(nf), c->nativeformats), 
00832       ast_getformatname_multiple(wf, sizeof(wf), c->writeformat), 
00833       ast_getformatname_multiple(rf, sizeof(rf), c->readformat),
00834       c->writetrans ? "Yes" : "No",
00835       c->readtrans ? "Yes" : "No",
00836       c->fds[0],
00837       c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
00838       c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
00839       (long)c->whentohangup,
00840       cdrtime, c->_bridge ? c->_bridge->name : "<none>", ast_bridged_channel(c) ? ast_bridged_channel(c)->name : "<none>", 
00841       c->context, c->exten, c->priority, c->callgroup, c->pickupgroup, ( c->appl ? c->appl : "(N/A)" ),
00842       ( c-> data ? S_OR(c->data, "(Empty)") : "(None)"),
00843       (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
00844    
00845    if (pbx_builtin_serialize_variables(c, &out))
00846       ast_cli(fd,"      Variables:\n%s\n", out->str);
00847    if (c->cdr && ast_cdr_serialize_variables(c->cdr, &out, '=', '\n', 1))
00848       ast_cli(fd,"  CDR Variables:\n%s\n", out->str);
00849    
00850    ast_channel_unlock(c);
00851    return RESULT_SUCCESS;
00852 }

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

Definition at line 381 of file cli.c.

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

00382 {
00383    time_t curtime;
00384    int printsec;
00385 
00386    switch (cmd) {
00387         case CLI_INIT:
00388       e->command = "core show uptime";
00389       e->usage =
00390          "Usage: core show uptime [seconds]\n"
00391          "       Shows Asterisk uptime information.\n"
00392          "       The seconds word returns the uptime in seconds only.\n";
00393       return NULL;
00394 
00395    case CLI_GENERATE:
00396       return (a->pos > e->args || a->n > 0) ? NULL : "seconds";
00397    }
00398    /* regular handler */
00399    if (a->argc == e->args+1 && !strcasecmp(a->argv[e->args],"seconds"))
00400       printsec = 1;
00401    else if (a->argc == e->args)
00402       printsec = 0;
00403    else
00404       return CLI_SHOWUSAGE;
00405    curtime = time(NULL);
00406    if (ast_startuptime)
00407       print_uptimestr(a->fd, curtime - ast_startuptime, "System uptime", printsec);
00408    if (ast_lastreloadtime)
00409       print_uptimestr(a->fd, curtime - ast_lastreloadtime, "Last reload", printsec);
00410    return CLI_SUCCESS;
00411 }

static int handle_softhangup int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 588 of file cli.c.

References ast_channel_unlock, ast_cli(), ast_get_channel_by_name_locked(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00589 {
00590    struct ast_channel *c=NULL;
00591    if (argc != 3)
00592       return RESULT_SHOWUSAGE;
00593    c = ast_get_channel_by_name_locked(argv[2]);
00594    if (c) {
00595       ast_cli(fd, "Requested Hangup on channel '%s'\n", c->name);
00596       ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
00597       ast_channel_unlock(c);
00598    } else
00599       ast_cli(fd, "%s is not a known channel\n", argv[2]);
00600    return RESULT_SUCCESS;
00601 }

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

Definition at line 259 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, 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.

Referenced by handle_unload_deprecated().

00260 {
00261    /* "module unload mod_1 [mod_2 .. mod_N]" */
00262    int x;
00263    int force = AST_FORCE_SOFT;
00264    char *s;
00265 
00266    switch (cmd) {
00267    case CLI_INIT:
00268       e->command = "module unload";
00269       e->usage =
00270          "Usage: module unload [-f|-h] <module_1> [<module_2> ... ]\n"
00271          "       Unloads the specified module from Asterisk. The -f\n"
00272          "       option causes the module to be unloaded even if it is\n"
00273          "       in use (may cause a crash) and the -h module causes the\n"
00274          "       module to be unloaded even if the module says it cannot, \n"
00275          "       which almost always will cause a crash.\n";
00276       return NULL;
00277 
00278    case CLI_GENERATE:
00279       return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0);
00280    }
00281    if (a->argc < e->args + 1)
00282       return CLI_SHOWUSAGE;
00283    x = e->args;   /* first argument */
00284    s = a->argv[x];
00285    if (s[0] == '-') {
00286       if (s[1] == 'f')
00287          force = AST_FORCE_FIRM;
00288       else if (s[1] == 'h')
00289          force = AST_FORCE_HARD;
00290       else
00291          return CLI_SHOWUSAGE;
00292       if (a->argc < e->args + 2) /* need at least one module name */
00293          return CLI_SHOWUSAGE;
00294       x++;  /* skip this argument */
00295    }
00296 
00297    for (; x < a->argc; x++) {
00298       if (ast_unload_resource(a->argv[x], force)) {
00299          ast_cli(a->fd, "Unable to unload resource %s\n", a->argv[x]);
00300          return CLI_FAILURE;
00301       }
00302    }
00303    return CLI_SUCCESS;
00304 }

static char* handle_unload_deprecated struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a
[static]
 

Definition at line 306 of file cli.c.

References CLI_INIT, ast_cli_entry::command, and handle_unload().

00307 {
00308    char *res = handle_unload(e, cmd, a);
00309    if (cmd == CLI_INIT)
00310       e->command = "unload";  /* XXX override */
00311    return res;
00312 }

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

Definition at line 187 of file cli.c.

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

00188 {
00189    int oldval = option_verbose;
00190    int newlevel;
00191    int atleast = 0;
00192    int fd = a->fd;
00193    int argc = a->argc;
00194    char **argv = a->argv;
00195    int *dst;
00196    char *what;
00197 
00198    switch (cmd) {
00199    case CLI_INIT:
00200       e->command = "core set {debug|verbose} [off|atleast]";
00201       e->usage =
00202          "Usage: core set {debug|verbose} [atleast] <level>\n"
00203          "       core set {debug|verbose} off\n"
00204          "       Sets level of debug or verbose messages to be displayed.\n"
00205          "  0 or off means no messages should be displayed.\n"
00206          "  Equivalent to -d[d[...]] or -v[v[v...]] on startup\n";
00207       return NULL;
00208 
00209    case CLI_GENERATE:
00210       return NULL;
00211    }
00212    /* all the above return, so we proceed with the handler.
00213     * we are guaranteed to be called with argc >= e->args;
00214     */
00215 
00216    if (argc < e->args)
00217       return CLI_SHOWUSAGE;
00218    if (!strcasecmp(argv[e->args - 2], "debug")) {
00219       dst = &option_debug;
00220       what = "Core debug";
00221    } else {
00222       dst = &option_verbose;
00223       what = "Verbosity";
00224    }
00225    if (argc == e->args && !strcasecmp(argv[e->args - 1], "off")) {
00226       newlevel = 0;
00227       goto done;
00228    }
00229    if (!strcasecmp(argv[e->args-1], "atleast"))
00230       atleast = 1;
00231    if (argc != e->args + atleast)
00232       return CLI_SHOWUSAGE;
00233    if (sscanf(argv[e->args + atleast - 1], "%d", &newlevel) != 1)
00234       return CLI_SHOWUSAGE;
00235 
00236 done:
00237    if (!atleast || newlevel > *dst)
00238       *dst = newlevel;
00239    if (oldval > 0 && *dst == 0)
00240       ast_cli(fd, "%s is now OFF\n", what);
00241    else if (*dst > 0) {
00242       if (oldval == *dst)
00243          ast_cli(fd, "%s is at least %d\n", what, *dst);
00244       else
00245          ast_cli(fd, "%s was %d and is now %d\n", what, oldval, *dst);
00246    }
00247 
00248    return CLI_SUCCESS;
00249 }

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

helper for final part of handle_help. if locked = 0 it's just "help_workhorse", otherwise assume the list is already locked and print an error message if not found.

Definition at line 1379 of file cli.c.

References ast_cli_entry::_full_cmd, ast_cli(), ast_join(), AST_LIST_LOCK, AST_LIST_UNLOCK, cli_next(), CLI_SUCCESS, ast_cli_entry::deprecated, cli_iterator::helpers, S_OR, and ast_cli_entry::summary.

Referenced by handle_help().

01380 {
01381    char matchstr[80] = "";
01382    struct ast_cli_entry *e;
01383    int len = 0;
01384    int found = 0;
01385    struct cli_iterator i = { NULL, NULL};
01386 
01387    if (match) {
01388       ast_join(matchstr, sizeof(matchstr), match);
01389       len = strlen(matchstr);
01390    }
01391    if (!locked)
01392       AST_LIST_LOCK(&helpers);
01393    while ( (e = cli_next(&i)) ) {
01394       /* Hide commands that start with '_' */
01395       if (e->_full_cmd[0] == '_')
01396          continue;
01397       /* Hide commands that are marked as deprecated. */
01398       if (e->deprecated)
01399          continue;
01400       if (match && strncasecmp(matchstr, e->_full_cmd, len))
01401          continue;
01402       ast_cli(fd, "%30.30s %s\n", e->_full_cmd, S_OR(e->summary, "<no description available>"));
01403       found++;
01404    }
01405    if (!locked)
01406       AST_LIST_UNLOCK(&helpers);
01407    if (!locked && !found && matchstr[0])
01408       ast_cli(fd, "No such command '%s'.\n", matchstr);
01409    return CLI_SUCCESS;
01410 }

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

References ast_strdupa, ast_strlen_zero(), cli_rsvd, s, strdup, and strsep().

Referenced by __ast_cli_generator().

01134 {
01135    int lw;
01136    char *s, *t1;
01137 
01138    *actual = 0;
01139    if (ast_strlen_zero(token))
01140       return NULL;
01141    if (ast_strlen_zero(word))
01142       word = "";  /* dummy */
01143    lw = strlen(word);
01144    if (strcspn(word, cli_rsvd) != lw)
01145       return NULL;   /* no match if word has reserved chars */
01146    if (strchr(cli_rsvd, token[0]) == NULL) { /* regular match */
01147       if (strncasecmp(token, word, lw))   /* no match */
01148          return NULL;
01149       *actual = 1;
01150       return (pos != 0) ? NULL : strdup(token);
01151    }
01152    /* now handle regexp match */
01153 
01154    /* Wildcard always matches, so we never do is_prefix on them */
01155 
01156    t1 = ast_strdupa(token + 1);  /* copy, skipping first char */
01157    while (pos >= 0 && (s = strsep(&t1, cli_rsvd)) && *s) {
01158       if (*s == '%') /* wildcard */
01159          continue;
01160       if (strncasecmp(s, word, lw)) /* no match */
01161          continue;
01162       (*actual)++;
01163       if (pos-- == 0)
01164          return strdup(s);
01165    }
01166    return NULL;
01167 }

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

Definition at line 320 of file cli.c.

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

Referenced by handle_modlist().

00321 {
00322    /* Comparing the like with the module */
00323    if (strcasestr(module, like) ) {
00324       ast_cli(climodentryfd, MODLIST_FORMAT, module, description, usecnt);
00325       return 1;
00326    } 
00327    return 0;
00328 }

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

returns true if there are more words to match

Definition at line 1583 of file cli.c.

Referenced by __ast_cli_generator().

01584 {
01585    int i;
01586    for (i = 0; dst[i]; i++) {
01587       if (dst[i][0] != '[')
01588          return -1;
01589    }
01590    return 0;
01591 }

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

Definition at line 1452 of file cli.c.

References ast_log(), ast_strdup, and LOG_WARNING.

Referenced by __ast_cli_generator(), agi_handle_command(), and ast_cli_command().

01453 {
01454    char *dup, *cur;
01455    int x = 0;
01456    int quoted = 0;
01457    int escaped = 0;
01458    int whitespace = 1;
01459    int dummy = 0;
01460 
01461    if (trailingwhitespace == NULL)
01462       trailingwhitespace = &dummy;
01463    *trailingwhitespace = 0;
01464    if (s == NULL) /* invalid, though! */
01465       return NULL;
01466    /* make a copy to store the parsed string */
01467    if (!(dup = ast_strdup(s)))
01468       return NULL;
01469 
01470    cur = dup;
01471    /* scan the original string copying into cur when needed */
01472    for (; *s ; s++) {
01473       if (x >= max - 1) {
01474          ast_log(LOG_WARNING, "Too many arguments, truncating at %s\n", s);
01475          break;
01476       }
01477       if (*s == '"' && !escaped) {
01478          quoted = !quoted;
01479          if (quoted && whitespace) {
01480             /* start a quoted string from previous whitespace: new argument */
01481             argv[x++] = cur;
01482             whitespace = 0;
01483          }
01484       } else if ((*s == ' ' || *s == '\t') && !(quoted || escaped)) {
01485          /* If we are not already in whitespace, and not in a quoted string or
01486             processing an escape sequence, and just entered whitespace, then
01487             finalize the previous argument and remember that we are in whitespace
01488          */
01489          if (!whitespace) {
01490             *cur++ = '\0';
01491             whitespace = 1;
01492          }
01493       } else if (*s == '\\' && !escaped) {
01494          escaped = 1;
01495       } else {
01496          if (whitespace) {
01497             /* we leave whitespace, and are not quoted. So it's a new argument */
01498             argv[x++] = cur;
01499             whitespace = 0;
01500          }
01501          *cur++ = *s;
01502          escaped = 0;
01503       }
01504    }
01505    /* Null terminate */
01506    *cur++ = '\0';
01507    /* XXX put a NULL in the last argument, because some functions that take
01508     * the array may want a null-terminated array.
01509     * argc still reflects the number of non-NULL entries.
01510     */
01511    argv[x] = NULL;
01512    *argc = x;
01513    *trailingwhitespace = whitespace;
01514    return dup;
01515 }

static void print_uptimestr int  fd,
time_t  timeval,
const char *  prefix,
int  printsec
[static]
 

Definition at line 330 of file cli.c.

References ast_cli(), ast_str_alloca, ast_str_append(), DAY, ESS, HOUR, MINUTE, NEEDCOMMA, ast_str::str, ast_str::used, WEEK, and YEAR.

Referenced by handle_showuptime().

00331 {
00332    int x; /* the main part - years, weeks, etc. */
00333    struct ast_str *out;
00334 
00335 #define SECOND (1)
00336 #define MINUTE (SECOND*60)
00337 #define HOUR (MINUTE*60)
00338 #define DAY (HOUR*24)
00339 #define WEEK (DAY*7)
00340 #define YEAR (DAY*365)
00341 #define NEEDCOMMA(x) ((x)? ",": "") /* define if we need a comma */
00342    if (timeval < 0)  /* invalid, nothing to show */
00343       return;
00344 
00345    if (printsec)  {  /* plain seconds output */
00346       ast_cli(fd, "%s: %lu\n", prefix, (u_long)timeval);
00347       return;
00348    }
00349    out = ast_str_alloca(256);
00350    if (timeval > YEAR) {
00351       x = (timeval / YEAR);
00352       timeval -= (x * YEAR);
00353       ast_str_append(&out, 0, "%d year%s%s ", x, ESS(x),NEEDCOMMA(timeval));
00354    }
00355    if (timeval > WEEK) {
00356       x = (timeval / WEEK);
00357       timeval -= (x * WEEK);
00358       ast_str_append(&out, 0, "%d week%s%s ", x, ESS(x),NEEDCOMMA(timeval));
00359    }
00360    if (timeval > DAY) {
00361       x = (timeval / DAY);
00362       timeval -= (x * DAY);
00363       ast_str_append(&out, 0, "%d day%s%s ", x, ESS(x),NEEDCOMMA(timeval));
00364    }
00365    if (timeval > HOUR) {
00366       x = (timeval / HOUR);
00367       timeval -= (x * HOUR);
00368       ast_str_append(&out, 0, "%d hour%s%s ", x, ESS(x),NEEDCOMMA(timeval));
00369    }
00370    if (timeval > MINUTE) {
00371       x = (timeval / MINUTE);
00372       timeval -= (x * MINUTE);
00373       ast_str_append(&out, 0, "%d minute%s%s ", x, ESS(x),NEEDCOMMA(timeval));
00374    }
00375    x = timeval;
00376    if (x > 0 || out->used == 0)  /* if there is nothing, print 0 seconds */
00377       ast_str_append(&out, 0, "%d second%s ", x, ESS(x));
00378    ast_cli(fd, "%s: %s\n", prefix, out->str);
00379 }

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

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

Referenced by ast_builtins_init().

01028 {
01029    int i;
01030    char buf[80];
01031 
01032    ast_join(buf, sizeof(buf), e->cmda);
01033    e->_full_cmd = strdup(buf);
01034    if (!e->_full_cmd) {
01035       ast_log(LOG_WARNING, "-- cannot allocate <%s>\n", buf);
01036       return -1;
01037    }
01038    e->cmdlen = strcspn(e->_full_cmd, cli_rsvd);
01039    for (i = 0; e->cmda[i]; i++)
01040       ;
01041    e->args = i;
01042    return 0;
01043 }

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

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

Referenced by __ast_cli_generator(), and find_cli().

01104 {
01105    int l;
01106    char *pos;
01107 
01108    if (ast_strlen_zero(cmd) || ast_strlen_zero(cli_word))
01109       return -1;
01110    if (!strchr(cli_rsvd, cli_word[0])) /* normal match */
01111       return (strcasecmp(cmd, cli_word) == 0) ? 1 : -1;
01112    /* regexp match, takes [foo|bar] or {foo|bar} */
01113    l = strlen(cmd);
01114    /* wildcard match - will extend in the future */
01115    if (l > 0 && cli_word[0] == '%') {
01116       return 1;   /* wildcard */
01117    }
01118    pos = strcasestr(cli_word, cmd);
01119    if (pos == NULL) /* not found, say ok if optional */
01120       return cli_word[0] == '[' ? 0 : -1;
01121    if (pos == cli_word) /* no valid match at the beginning */
01122       return -1;
01123    if (strchr(cli_rsvd, pos[-1]) && strchr(cli_rsvd, pos[l]))
01124       return 1;   /* valid match */
01125    return -1;  /* not found */
01126 }


Variable Documentation

struct ast_cli_entry builtins[] [static]
 

Definition at line 954 of file cli.c.

Referenced by ast_builtins_init(), cli_next(), and load_pbx().

struct ast_cli_entry cli_cli[] [static]
 

Definition at line 978 of file cli.c.

Referenced by ast_builtins_init().

struct ast_cli_entry cli_debug_channel_deprecated = NEW_CLI(handle_debugchan_deprecated, "Enable debugging on channel") [static]
 

Definition at line 971 of file cli.c.

struct ast_cli_entry cli_module_load_deprecated = NEW_CLI(handle_load_deprecated, "Load a module") [static]
 

Definition at line 972 of file cli.c.

struct ast_cli_entry cli_module_reload_deprecated = NEW_CLI(handle_reload_deprecated, "reload modules by name") [static]
 

Definition at line 973 of file cli.c.

struct ast_cli_entry cli_module_unload_deprecated = NEW_CLI(handle_unload_deprecated, "unload modules by name") [static]
 

Definition at line 974 of file cli.c.

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

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

Definition at line 1021 of file cli.c.

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

int climodentryfd = -1 [static]
 

Definition at line 318 of file cli.c.

Referenced by handle_modlist(), and modlist_modentry().

const char commandcomplete_help[] [static]
 

Initial value:

 
"Usage: _command complete \"<line>\" text state\n"
"       This function is used internally to help with command completion and should.\n"
"       never be called by the user directly.\n"

Definition at line 573 of file cli.c.

const char commandmatchesarray_help[] [static]
 

Initial value:

 
"Usage: _command matchesarray \"<line>\" text \n"
"       This function is used internally to help with command completion and should.\n"
"       never be called by the user directly.\n"

Definition at line 583 of file cli.c.

const char commandnummatches_help[] [static]
 

Initial value:

 
"Usage: _command nummatches \"<line>\" text \n"
"       This function is used internally to help with command completion and should.\n"
"       never be called by the user directly.\n"

Definition at line 578 of file cli.c.

const char group_show_channels_help[] [static]
 

Initial value:

 
"Usage: group show channels [pattern]\n"
"       Lists all currently active channels with channel group(s) specified.\n"
"       Optional regular expression pattern is matched to group names for each\n"
"       channel.\n"

Definition at line 86 of file cli.c.

const char logger_mute_help[] [static]
 

Initial value:

 
"Usage: logger mute\n"
"       Disables logging output to the current console, making it possible to\n"
"       gather information without being disturbed by scrolling lines.\n"

Definition at line 76 of file cli.c.

const char showchan_help[] [static]
 

Initial value:

 
"Usage: core show channel <channel>\n"
"       Shows lots of information about the specified channel.\n"

Definition at line 569 of file cli.c.

const char softhangup_help[] [static]
 

Initial value:

"Usage: soft hangup <channel>\n"
"       Request that a channel be hung up. The hangup takes effect\n"
"       the next time the driver reads or writes from the channel\n"

Definition at line 81 of file cli.c.


Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen