res_clialiases.c File Reference

CLI Aliases. More...

#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/astobj2.h"

Include dependency graph for res_clialiases.c:

Go to the source code of this file.

Data Structures

struct  cli_alias

Defines

#define FORMAT   "%-50.50s %-50.50s\n"
#define MAX_ALIAS_BUCKETS   53

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int alias_cmp_cb (void *obj, void *arg, int flags)
 Comparison function used for aliases.
static int alias_hash_cb (const void *obj, const int flags)
 Hashing function used for aliases.
static int alias_name_cb (void *obj, void *arg, int flags)
 Callback for finding an alias based on name.
static char * alias_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI Command to display CLI Aliases.
static int alias_unregister_cb (void *obj, void *arg, int flags)
 Callback for unregistering an alias.
static char * cli_alias_passthrough (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Function which passes through an aliased CLI command to the real one.
static void load_config (int reload)
 Function called to load or reload the configuration file.
static int load_module (void)
 Load the module.
static int reload_module (void)
 Function called to reload the module.
static int unload_module (void)
 Function called to unload the module.

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "CLI Aliases" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_alias []
 CLI commands to interact with things.
static struct ao2_containercli_aliases
static const char config_file [] = "cli_aliases.conf"


Detailed Description

CLI Aliases.

Author:
Joshua Colp <jcolp@digium.com> 
This module provides the capability to create aliases to other CLI commands.

Definition in file res_clialiases.c.


Define Documentation

#define FORMAT   "%-50.50s %-50.50s\n"

#define MAX_ALIAS_BUCKETS   53

Maximum number of buckets for CLI aliases

Definition at line 52 of file res_clialiases.c.

Referenced by load_module().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 307 of file res_clialiases.c.

static void __unreg_module ( void   )  [static]

Definition at line 307 of file res_clialiases.c.

static int alias_cmp_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Comparison function used for aliases.

Definition at line 73 of file res_clialiases.c.

References cli_alias::cli_entry, CMP_MATCH, CMP_STOP, and ast_cli_entry::command.

Referenced by load_module().

00074 {
00075    const struct cli_alias *alias0 = obj, *alias1 = arg;
00076 
00077    return (alias0->cli_entry.command == alias1->cli_entry.command ? CMP_MATCH | CMP_STOP : 0);
00078 }

static int alias_hash_cb ( const void *  obj,
const int  flags 
) [static]

Hashing function used for aliases.

Definition at line 66 of file res_clialiases.c.

References cli_alias::alias, ast_str_hash(), cli_alias::cli_entry, and ast_cli_entry::command.

Referenced by load_module().

00067 {
00068    const struct cli_alias *alias = obj;
00069    return ast_str_hash(alias->cli_entry.command);
00070 }

static int alias_name_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Callback for finding an alias based on name.

Definition at line 93 of file res_clialiases.c.

References cli_alias::alias, CMP_MATCH, CMP_STOP, and name.

Referenced by load_config().

00094 {
00095    struct cli_alias *alias = obj;
00096    char *name = arg;
00097 
00098    return !strcmp(alias->alias, name) ? CMP_MATCH | CMP_STOP : 0;
00099 }

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

CLI Command to display CLI Aliases.

Definition at line 159 of file res_clialiases.c.

References cli_alias::alias, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT, NULL, cli_alias::real_cmd, and ast_cli_entry::usage.

00160 {
00161 #define FORMAT "%-50.50s %-50.50s\n"
00162    struct cli_alias *alias;
00163    struct ao2_iterator i;
00164 
00165    switch (cmd) {
00166    case CLI_INIT:
00167       e->command = "cli show aliases";
00168       e->usage =
00169          "Usage: cli show aliases\n"
00170          "       Displays a list of aliased CLI commands.\n";
00171       return NULL;
00172    case CLI_GENERATE:
00173       return NULL;
00174    }
00175 
00176    ast_cli(a->fd, FORMAT, "Alias Command", "Real Command");
00177 
00178    i = ao2_iterator_init(cli_aliases, 0);
00179    for (; (alias = ao2_iterator_next(&i)); ao2_ref(alias, -1)) {
00180       ast_cli(a->fd, FORMAT, alias->alias, alias->real_cmd);
00181    }
00182    ao2_iterator_destroy(&i);
00183 
00184    return CLI_SUCCESS;
00185 #undef FORMAT
00186 }

static int alias_unregister_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Callback for unregistering an alias.

Definition at line 81 of file res_clialiases.c.

References cli_alias::alias, ast_cli_unregister(), cli_alias::cli_entry, CMP_MATCH, and ast_cli_entry::command.

Referenced by load_config(), and unload_module().

00082 {
00083    struct cli_alias *alias = obj;
00084 
00085    /* Unregister the CLI entry from the core */
00086    ast_cli_unregister(&alias->cli_entry);
00087 
00088    /* We can determine if this worked or not by looking at the cli_entry itself */
00089    return !alias->cli_entry.command ? CMP_MATCH : 0;
00090 }

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

Function which passes through an aliased CLI command to the real one.

Definition at line 102 of file res_clialiases.c.

References cli_alias::alias, ao2_find, ao2_ref, ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli_command, ast_cli_generator(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_strlen_zero, cli_alias::cli_entry, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, generator, ast_cli_args::line, ast_cli_args::n, NULL, OBJ_POINTER, cli_alias::real_cmd, and ast_cli_args::word.

Referenced by load_config().

00103 {
00104    struct cli_alias *alias;
00105    struct cli_alias tmp = {
00106       .cli_entry.command = e->command,
00107    };
00108    char *generator;
00109    const char *line;
00110 
00111    /* Try to find the alias based on the CLI entry */
00112    if (!(alias = ao2_find(cli_aliases, &tmp, OBJ_POINTER))) {
00113       return 0;
00114    }
00115 
00116    switch (cmd) {
00117    case CLI_INIT:
00118       ao2_ref(alias, -1);
00119       return NULL;
00120    case CLI_GENERATE:
00121       line = a->line;
00122       line += (strlen(alias->alias));
00123       if (!strncasecmp(alias->alias, alias->real_cmd, strlen(alias->alias))) {
00124          generator = NULL;
00125       } else if (!ast_strlen_zero(a->word)) {
00126          struct ast_str *real_cmd = ast_str_alloca(strlen(alias->real_cmd) + strlen(line) + 1);
00127          ast_str_append(&real_cmd, 0, "%s%s", alias->real_cmd, line);
00128          generator = ast_cli_generator(ast_str_buffer(real_cmd), a->word, a->n);
00129       } else {
00130          generator = ast_cli_generator(alias->real_cmd, a->word, a->n);
00131       }
00132       ao2_ref(alias, -1);
00133       return generator;
00134    }
00135 
00136    /* If they gave us extra arguments we need to construct a string to pass in */
00137    if (a->argc != e->args) {
00138       struct ast_str *real_cmd = ast_str_alloca(2048);
00139       int i;
00140 
00141       ast_str_append(&real_cmd, 0, "%s", alias->real_cmd);
00142 
00143       /* Add the additional arguments that have been passed in */
00144       for (i = e->args + 1; i <= a->argc; i++) {
00145          ast_str_append(&real_cmd, 0, " %s", a->argv[i - 1]);
00146       }
00147 
00148       ast_cli_command(a->fd, ast_str_buffer(real_cmd));
00149    } else {
00150       ast_cli_command(a->fd, alias->real_cmd);
00151    }
00152 
00153    ao2_ref(alias, -1);
00154 
00155    return CLI_SUCCESS;
00156 }

static void load_config ( int  reload  )  [static]

Function called to load or reload the configuration file.

Definition at line 194 of file res_clialiases.c.

References cli_alias::alias, alias_name_cb(), alias_unregister_cb(), ao2_alloc, ao2_callback, ao2_link, ao2_ref, ast_cli_register(), ast_config_destroy(), ast_config_load, ast_log, ast_variable_browse(), ast_verb, cli_alias_passthrough(), cli_alias::cli_entry, ast_cli_entry::command, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, ast_cli_entry::handler, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, cli_alias::real_cmd, ast_cli_entry::usage, and ast_variable::value.

00195 {
00196    struct ast_config *cfg = NULL;
00197    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00198    struct cli_alias *alias;
00199    struct ast_variable *v, *v1;
00200 
00201    if (!(cfg = ast_config_load(config_file, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
00202       ast_log(LOG_ERROR, "res_clialiases configuration file '%s' not found\n", config_file);
00203       return;
00204    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
00205       return;
00206    }
00207 
00208    /* Destroy any existing CLI aliases */
00209    if (reload) {
00210       ao2_callback(cli_aliases, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, alias_unregister_cb, NULL);
00211    }
00212 
00213    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
00214       if (strcmp(v->name, "template")) {
00215          ast_log(LOG_WARNING, "%s is not a correct option in [%s]\n", v->name, "general");
00216          continue;
00217       }
00218       /* Read in those there CLI aliases */
00219       for (v1 = ast_variable_browse(cfg, v->value); v1; v1 = v1->next) {
00220          struct cli_alias *existing = ao2_callback(cli_aliases, 0, alias_name_cb, (char*)v1->name);
00221 
00222          if (existing) {
00223             ast_log(LOG_WARNING, "Alias '%s' could not be unregistered and has been retained\n",
00224                existing->alias);
00225             ao2_ref(existing, -1);
00226             continue;
00227          }
00228 
00229          if (!(alias = ao2_alloc((sizeof(*alias) + strlen(v1->name) + strlen(v1->value) + 2), NULL))) {
00230             continue;
00231          }
00232          alias->alias = ((char *) alias) + sizeof(*alias);
00233          alias->real_cmd = ((char *) alias->alias) + strlen(v1->name) + 1;
00234          strcpy(alias->alias, v1->name);
00235          strcpy(alias->real_cmd, v1->value);
00236          alias->cli_entry.handler = cli_alias_passthrough;
00237          alias->cli_entry.command = alias->alias;
00238          alias->cli_entry.usage = "Aliased CLI Command\n";
00239 
00240          if (ast_cli_register(&alias->cli_entry)) {
00241             ao2_ref(alias, -1);
00242             continue;
00243          }
00244          ao2_link(cli_aliases, alias);
00245          ast_verb(2, "Aliased CLI command '%s' to '%s'\n", v1->name, v1->value);
00246          ao2_ref(alias, -1);
00247       }
00248    }
00249 
00250    ast_config_destroy(cfg);
00251 
00252    return;
00253 }

static int load_module ( void   )  [static]

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 289 of file res_clialiases.c.

References alias_cmp_cb(), alias_hash_cb(), ao2_container_alloc, ARRAY_LEN, ast_cli_register_multiple(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, load_config(), and MAX_ALIAS_BUCKETS.

00290 {
00291    if (!(cli_aliases = ao2_container_alloc(MAX_ALIAS_BUCKETS, alias_hash_cb, alias_cmp_cb))) {
00292       return AST_MODULE_LOAD_DECLINE;
00293    }
00294 
00295    load_config(0);
00296 
00297    ast_cli_register_multiple(cli_alias, ARRAY_LEN(cli_alias));
00298 
00299    return AST_MODULE_LOAD_SUCCESS;
00300 }

static int reload_module ( void   )  [static]

Function called to reload the module.

Definition at line 256 of file res_clialiases.c.

References load_config().

00257 {
00258    load_config(1);
00259    return 0;
00260 }

static int unload_module ( void   )  [static]

Function called to unload the module.

Definition at line 263 of file res_clialiases.c.

References alias_unregister_cb(), ao2_callback, ao2_container_count(), ao2_ref, ARRAY_LEN, ast_cli_unregister_multiple(), ast_log, LOG_ERROR, NULL, OBJ_MULTIPLE, OBJ_NODATA, and OBJ_UNLINK.

00264 {
00265    ao2_callback(cli_aliases, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, alias_unregister_cb, NULL);
00266 
00267    if (ao2_container_count(cli_aliases)) {
00268       ast_log(LOG_ERROR, "Could not unregister all CLI aliases\n");
00269       return -1;
00270    }
00271 
00272    ao2_ref(cli_aliases, -1);
00273 
00274    ast_cli_unregister_multiple(cli_alias, ARRAY_LEN(cli_alias));
00275 
00276    return 0;
00277 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "CLI Aliases" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, } [static]

Definition at line 307 of file res_clialiases.c.

Definition at line 307 of file res_clialiases.c.

struct ast_cli_entry cli_alias[] [static]

Initial value:

 {
   AST_CLI_DEFINE(alias_show, "Show CLI command aliases"),
}
CLI commands to interact with things.

Definition at line 189 of file res_clialiases.c.

struct ao2_container* cli_aliases [static]

Definition at line 63 of file res_clialiases.c.

const char config_file[] = "cli_aliases.conf" [static]

Configuration file used for this application

Definition at line 55 of file res_clialiases.c.


Generated on Thu Apr 16 06:32:43 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6