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: 407205 $")
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 int alias_unregister_cb(void *obj, void *arg, int flags)
00073 {
00074 struct cli_alias *alias = obj;
00075
00076
00077 ast_cli_unregister(&alias->cli_entry);
00078
00079
00080 return !alias->cli_entry.command ? CMP_MATCH : 0;
00081 }
00082
00083
00084 static int alias_name_cb(void *obj, void *arg, int flags)
00085 {
00086 struct cli_alias *alias = obj;
00087 char *name = arg;
00088
00089 return !strcmp(alias->alias, name) ? CMP_MATCH | CMP_STOP : 0;
00090 }
00091
00092
00093 static char *cli_alias_passthrough(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00094 {
00095 struct cli_alias *alias;
00096 struct cli_alias tmp = {
00097 .cli_entry.command = e->command,
00098 };
00099 char *generator;
00100 const char *line;
00101
00102
00103 if (!(alias = ao2_find(cli_aliases, &tmp, OBJ_POINTER))) {
00104 return 0;
00105 }
00106
00107 switch (cmd) {
00108 case CLI_INIT:
00109 ao2_ref(alias, -1);
00110 return NULL;
00111 case CLI_GENERATE:
00112 line = a->line;
00113 line += (strlen(alias->alias));
00114 if (!strncasecmp(alias->alias, alias->real_cmd, strlen(alias->alias))) {
00115 generator = NULL;
00116 } else if (!ast_strlen_zero(a->word)) {
00117 struct ast_str *real_cmd = ast_str_alloca(strlen(alias->real_cmd) + strlen(line) + 1);
00118 ast_str_append(&real_cmd, 0, "%s%s", alias->real_cmd, line);
00119 generator = ast_cli_generator(ast_str_buffer(real_cmd), a->word, a->n);
00120 } else {
00121 generator = ast_cli_generator(alias->real_cmd, a->word, a->n);
00122 }
00123 ao2_ref(alias, -1);
00124 return generator;
00125 }
00126
00127
00128 if (a->argc != e->args) {
00129 struct ast_str *real_cmd = ast_str_alloca(2048);
00130 int i;
00131
00132 ast_str_append(&real_cmd, 0, "%s", alias->real_cmd);
00133
00134
00135 for (i = e->args + 1; i <= a->argc; i++) {
00136 ast_str_append(&real_cmd, 0, " %s", a->argv[i - 1]);
00137 }
00138
00139 ast_cli_command(a->fd, ast_str_buffer(real_cmd));
00140 } else {
00141 ast_cli_command(a->fd, alias->real_cmd);
00142 }
00143
00144 ao2_ref(alias, -1);
00145
00146 return CLI_SUCCESS;
00147 }
00148
00149
00150 static char *alias_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00151 {
00152 #define FORMAT "%-50.50s %-50.50s\n"
00153 struct cli_alias *alias;
00154 struct ao2_iterator i;
00155
00156 switch (cmd) {
00157 case CLI_INIT:
00158 e->command = "cli show aliases";
00159 e->usage =
00160 "Usage: cli show aliases\n"
00161 " Displays a list of aliased CLI commands.\n";
00162 return NULL;
00163 case CLI_GENERATE:
00164 return NULL;
00165 }
00166
00167 ast_cli(a->fd, FORMAT, "Alias Command", "Real Command");
00168
00169 i = ao2_iterator_init(cli_aliases, 0);
00170 for (; (alias = ao2_iterator_next(&i)); ao2_ref(alias, -1)) {
00171 ast_cli(a->fd, FORMAT, alias->alias, alias->real_cmd);
00172 }
00173 ao2_iterator_destroy(&i);
00174
00175 return CLI_SUCCESS;
00176 #undef FORMAT
00177 }
00178
00179
00180 static struct ast_cli_entry cli_alias[] = {
00181 AST_CLI_DEFINE(alias_show, "Show CLI command aliases"),
00182 };
00183
00184
00185 static void load_config(int reload)
00186 {
00187 struct ast_config *cfg = NULL;
00188 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00189 struct cli_alias *alias;
00190 struct ast_variable *v, *v1;
00191
00192 if (!(cfg = ast_config_load(config_file, config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
00193 ast_log(LOG_ERROR, "res_clialiases configuration file '%s' not found\n", config_file);
00194 return;
00195 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
00196 return;
00197 }
00198
00199
00200 if (reload) {
00201 ao2_callback(cli_aliases, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, alias_unregister_cb, NULL);
00202 }
00203
00204 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
00205 if (strcmp(v->name, "template")) {
00206 ast_log(LOG_WARNING, "%s is not a correct option in [%s]\n", v->name, "general");
00207 continue;
00208 }
00209
00210 for (v1 = ast_variable_browse(cfg, v->value); v1; v1 = v1->next) {
00211 struct cli_alias *existing = ao2_callback(cli_aliases, 0, alias_name_cb, (char*)v1->name);
00212
00213 if (existing) {
00214 ast_log(LOG_WARNING, "Alias '%s' could not be unregistered and has been retained\n",
00215 existing->alias);
00216 ao2_ref(existing, -1);
00217 continue;
00218 }
00219
00220 if (!(alias = ao2_alloc((sizeof(*alias) + strlen(v1->name) + strlen(v1->value) + 2), NULL))) {
00221 continue;
00222 }
00223 alias->alias = ((char *) alias) + sizeof(*alias);
00224 alias->real_cmd = ((char *) alias->alias) + strlen(v1->name) + 1;
00225 strcpy(alias->alias, v1->name);
00226 strcpy(alias->real_cmd, v1->value);
00227 alias->cli_entry.handler = cli_alias_passthrough;
00228 alias->cli_entry.command = alias->alias;
00229 alias->cli_entry.usage = "Aliased CLI Command\n";
00230
00231 if (ast_cli_register(&alias->cli_entry)) {
00232 ao2_ref(alias, -1);
00233 continue;
00234 }
00235 ao2_link(cli_aliases, alias);
00236 ast_verbose(VERBOSE_PREFIX_2 "Aliased CLI command '%s' to '%s'\n", v1->name, v1->value);
00237 ao2_ref(alias, -1);
00238 }
00239 }
00240
00241 ast_config_destroy(cfg);
00242
00243 return;
00244 }
00245
00246
00247 static int reload_module(void)
00248 {
00249 load_config(1);
00250 return 0;
00251 }
00252
00253
00254 static int unload_module(void)
00255 {
00256 ao2_callback(cli_aliases, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, alias_unregister_cb, NULL);
00257
00258 if (ao2_container_count(cli_aliases)) {
00259 ast_log(LOG_ERROR, "Could not unregister all CLI aliases\n");
00260 return -1;
00261 }
00262
00263 ao2_ref(cli_aliases, -1);
00264
00265 ast_cli_unregister_multiple(cli_alias, ARRAY_LEN(cli_alias));
00266
00267 return 0;
00268 }
00269
00270
00271 static int load_module(void)
00272 {
00273 if (!(cli_aliases = ao2_container_alloc(MAX_ALIAS_BUCKETS, alias_hash_cb, alias_cmp_cb))) {
00274 return AST_MODULE_LOAD_DECLINE;
00275 }
00276
00277 load_config(0);
00278
00279 ast_cli_register_multiple(cli_alias, ARRAY_LEN(cli_alias));
00280
00281 return AST_MODULE_LOAD_SUCCESS;
00282 }
00283
00284 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "CLI Aliases",
00285 .load = load_module,
00286 .unload = unload_module,
00287 .reload = reload_module,
00288 );