00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00036
00037 #include "asterisk/module.h"
00038 #include "asterisk/config.h"
00039 #include "asterisk/cli.h"
00040 #include "asterisk/astobj2.h"
00041
00042
00043 #define MAX_ALIAS_BUCKETS 53
00044
00045
00046 static const char config_file[] = "cli_aliases.conf";
00047
00048 struct cli_alias {
00049 struct ast_cli_entry cli_entry;
00050 char *alias;
00051 char *real_cmd;
00052 };
00053
00054 static struct ao2_container *cli_aliases;
00055
00056
00057 static int alias_hash_cb(const void *obj, const int flags)
00058 {
00059 const struct cli_alias *alias = obj;
00060 return ast_str_hash(alias->cli_entry.command);
00061 }
00062
00063
00064 static int alias_cmp_cb(void *obj, void *arg, int flags)
00065 {
00066 const struct cli_alias *alias0 = obj, *alias1 = arg;
00067
00068 return (alias0->cli_entry.command == alias1->cli_entry.command ? CMP_MATCH | CMP_STOP : 0);
00069 }
00070
00071
00072 static void alias_destroy(void *obj)
00073 {
00074 struct cli_alias *alias = obj;
00075
00076
00077 ast_cli_unregister(&alias->cli_entry);
00078
00079 return;
00080 }
00081
00082
00083 static char *cli_alias_passthrough(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00084 {
00085 struct cli_alias *alias;
00086 struct cli_alias tmp = {
00087 .cli_entry.command = e->command,
00088 };
00089 char *generator;
00090 const char *line;
00091
00092
00093 if (!(alias = ao2_find(cli_aliases, &tmp, OBJ_POINTER))) {
00094 return 0;
00095 }
00096
00097 switch (cmd) {
00098 case CLI_INIT:
00099 ao2_ref(alias, -1);
00100 return NULL;
00101 case CLI_GENERATE:
00102 line = a->line;
00103 line += (strlen(alias->alias));
00104 if (!strncasecmp(alias->alias, alias->real_cmd, strlen(alias->alias))) {
00105 generator = NULL;
00106 } else if (!ast_strlen_zero(a->word)) {
00107 struct ast_str *real_cmd = ast_str_alloca(strlen(alias->real_cmd) + strlen(line) + 1);
00108 ast_str_append(&real_cmd, 0, "%s%s", alias->real_cmd, line);
00109 generator = ast_cli_generator(ast_str_buffer(real_cmd), a->word, a->n);
00110 } else {
00111 generator = ast_cli_generator(alias->real_cmd, a->word, a->n);
00112 }
00113 ao2_ref(alias, -1);
00114 return generator;
00115 }
00116
00117
00118 if (a->argc != e->args) {
00119 struct ast_str *real_cmd = ast_str_alloca(2048);
00120 int i;
00121
00122 ast_str_append(&real_cmd, 0, "%s", alias->real_cmd);
00123
00124
00125 for (i = e->args + 1; i <= a->argc; i++) {
00126 ast_str_append(&real_cmd, 0, " %s", a->argv[i - 1]);
00127 }
00128
00129 ast_cli_command(a->fd, ast_str_buffer(real_cmd));
00130 } else {
00131 ast_cli_command(a->fd, alias->real_cmd);
00132 }
00133
00134 ao2_ref(alias, -1);
00135
00136 return CLI_SUCCESS;
00137 }
00138
00139
00140 static char *alias_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00141 {
00142 #define FORMAT "%-50.50s %-50.50s\n"
00143 struct cli_alias *alias;
00144 struct ao2_iterator i;
00145
00146 switch (cmd) {
00147 case CLI_INIT:
00148 e->command = "cli show aliases";
00149 e->usage =
00150 "Usage: cli show aliases\n"
00151 " Displays a list of aliased CLI commands.\n";
00152 return NULL;
00153 case CLI_GENERATE:
00154 return NULL;
00155 }
00156
00157 ast_cli(a->fd, FORMAT, "Alias Command", "Real Command");
00158
00159 i = ao2_iterator_init(cli_aliases, 0);
00160 for (; (alias = ao2_iterator_next(&i)); ao2_ref(alias, -1)) {
00161 ast_cli(a->fd, FORMAT, alias->alias, alias->real_cmd);
00162 }
00163 ao2_iterator_destroy(&i);
00164
00165 return CLI_SUCCESS;
00166 #undef FORMAT
00167 }
00168
00169
00170 static struct ast_cli_entry cli_alias[] = {
00171 AST_CLI_DEFINE(alias_show, "Show CLI command aliases"),
00172 };
00173
00174
00175 static void load_config(int reload)
00176 {
00177 struct ast_config *cfg = NULL;
00178 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00179 struct cli_alias *alias;
00180 struct ast_variable *v, *v1;
00181
00182 if (!(cfg = ast_config_load(config_file, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
00183 ast_log(LOG_ERROR, "res_clialiases configuration file '%s' not found\n", config_file);
00184 return;
00185 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
00186 return;
00187 }
00188
00189
00190 if (reload) {
00191 ao2_callback(cli_aliases, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
00192 }
00193
00194 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
00195 if (strcmp(v->name, "template")) {
00196 ast_log(LOG_WARNING, "%s is not a correct option in [%s]\n", v->name, "general");
00197 continue;
00198 }
00199
00200 for (v1 = ast_variable_browse(cfg, v->value); v1; v1 = v1->next) {
00201 if (!(alias = ao2_alloc((sizeof(*alias) + strlen(v1->name) + strlen(v1->value) + 2), alias_destroy))) {
00202 continue;
00203 }
00204 alias->alias = ((char *) alias) + sizeof(*alias);
00205 alias->real_cmd = ((char *) alias->alias) + strlen(v1->name) + 1;
00206 strcpy(alias->alias, v1->name);
00207 strcpy(alias->real_cmd, v1->value);
00208 alias->cli_entry.handler = cli_alias_passthrough;
00209 alias->cli_entry.command = alias->alias;
00210 alias->cli_entry.usage = "Aliased CLI Command\n";
00211
00212 ast_cli_register(&alias->cli_entry);
00213 ao2_link(cli_aliases, alias);
00214 ast_verbose(VERBOSE_PREFIX_2 "Aliased CLI command '%s' to '%s'\n", v1->name, v1->value);
00215 ao2_ref(alias, -1);
00216 }
00217 }
00218
00219 ast_config_destroy(cfg);
00220
00221 return;
00222 }
00223
00224
00225 static int reload_module(void)
00226 {
00227 load_config(1);
00228 return 0;
00229 }
00230
00231
00232 static int unload_module(void)
00233 {
00234 ao2_ref(cli_aliases, -1);
00235
00236 ast_cli_unregister_multiple(cli_alias, ARRAY_LEN(cli_alias));
00237
00238 return 0;
00239 }
00240
00241
00242 static int load_module(void)
00243 {
00244 if (!(cli_aliases = ao2_container_alloc(MAX_ALIAS_BUCKETS, alias_hash_cb, alias_cmp_cb))) {
00245 return AST_MODULE_LOAD_DECLINE;
00246 }
00247
00248 load_config(0);
00249
00250 ast_cli_register_multiple(cli_alias, ARRAY_LEN(cli_alias));
00251
00252 return AST_MODULE_LOAD_SUCCESS;
00253 }
00254
00255 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "CLI Aliases",
00256 .load = load_module,
00257 .unload = unload_module,
00258 .reload = reload_module,
00259 );