mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 12:36:58 +00:00
Handle deprecated (aliased) option names with the config options api
Add a simple way to register "deprecated" option names that alias to a different "current" name. Review: https://reviewboard.asterisk.org/r/2026/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@370043 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -12,8 +12,8 @@ boolopt=true
|
|||||||
boolflag1=true
|
boolflag1=true
|
||||||
boolflag2=false
|
boolflag2=false
|
||||||
boolflag3=true
|
boolflag3=true
|
||||||
acldenyopt=0.0.0.0/0
|
deny=0.0.0.0/0
|
||||||
aclpermitopt=1.2.3.4/32
|
permit=1.2.3.4/32
|
||||||
codecopt=!all,ulaw,g729
|
codecopt=!all,ulaw,g729
|
||||||
stropt=test
|
stropt=test
|
||||||
customopt=yes
|
customopt=yes
|
||||||
|
@@ -496,7 +496,8 @@ int __aco_option_register(struct aco_info *info, const char *name, enum aco_matc
|
|||||||
* \param opt_type The option type for default option type handling
|
* \param opt_type The option type for default option type handling
|
||||||
* \param flags \a type specific flags, stored in the option and available to the handler
|
* \param flags \a type specific flags, stored in the option and available to the handler
|
||||||
*
|
*
|
||||||
* \returns An option on success, NULL on failure
|
* \retval 0 Success
|
||||||
|
* \retval -1 Failure
|
||||||
*/
|
*/
|
||||||
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags, ...) \
|
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags, ...) \
|
||||||
__aco_option_register(info, name, matchtype, types, default_val, opt_type, NULL, flags, VA_NARGS(__VA_ARGS__), __VA_ARGS__);
|
__aco_option_register(info, name, matchtype, types, default_val, opt_type, NULL, flags, VA_NARGS(__VA_ARGS__), __VA_ARGS__);
|
||||||
@@ -509,10 +510,22 @@ int __aco_option_register(struct aco_info *info, const char *name, enum aco_matc
|
|||||||
* \param handler The handler callback for the option
|
* \param handler The handler callback for the option
|
||||||
* \param flags \a type specific flags, stored in the option and available to the handler
|
* \param flags \a type specific flags, stored in the option and available to the handler
|
||||||
*
|
*
|
||||||
* \returns An option on success, NULL on failure
|
* \retval 0 Success
|
||||||
|
* \retval -1 Failure
|
||||||
*/
|
*/
|
||||||
#define aco_option_register_custom(info, name, matchtype, type, default_val, handler, flags) \
|
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags) \
|
||||||
__aco_option_register(info, name, matchtype, type, default_val, OPT_CUSTOM_T, handler, flags, 0);
|
__aco_option_register(info, name, matchtype, types, default_val, OPT_CUSTOM_T, handler, flags, 0);
|
||||||
|
|
||||||
|
/*! \brief Register a deprecated (and aliased) config option
|
||||||
|
* \param info A pointer to the aco_info struct
|
||||||
|
* \param name The name of the deprecated option
|
||||||
|
* \param types An array of valid option types for matching categories to the correct struct type
|
||||||
|
* \param aliased_to The name of the option that this deprecated option matches to
|
||||||
|
*
|
||||||
|
* \retval 0 Success
|
||||||
|
* \retval -1 Failure
|
||||||
|
*/
|
||||||
|
int aco_option_register_deprecated(struct aco_info *info, const char *name, struct aco_type **types, const char *aliased_to);
|
||||||
|
|
||||||
/*! \note Everything below this point is to handle converting varargs
|
/*! \note Everything below this point is to handle converting varargs
|
||||||
* containing field names, to varargs containing a count of args, followed
|
* containing field names, to varargs containing a count of args, followed
|
||||||
|
@@ -57,13 +57,15 @@ struct aco_type_internal {
|
|||||||
|
|
||||||
struct aco_option {
|
struct aco_option {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
const char *aliased_to;
|
||||||
|
const char *default_val;
|
||||||
enum aco_matchtype match_type;
|
enum aco_matchtype match_type;
|
||||||
regex_t *name_regex;
|
regex_t *name_regex;
|
||||||
const char *default_val;
|
|
||||||
struct aco_type **obj;
|
struct aco_type **obj;
|
||||||
enum aco_option_type type;
|
enum aco_option_type type;
|
||||||
aco_option_handler handler;
|
aco_option_handler handler;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
unsigned char deprecated:1;
|
||||||
size_t argc;
|
size_t argc;
|
||||||
intptr_t args[0];
|
intptr_t args[0];
|
||||||
};
|
};
|
||||||
@@ -136,11 +138,51 @@ static regex_t *build_regex(const char *text)
|
|||||||
return regex;
|
return regex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int link_option_to_types(struct aco_type **types, struct aco_option *opt)
|
||||||
|
{
|
||||||
|
size_t idx = 0;
|
||||||
|
struct aco_type *type;
|
||||||
|
|
||||||
|
while ((type = types[idx++])) {
|
||||||
|
if (!ao2_link(type->internal->opts, opt)) {
|
||||||
|
while (--idx) {
|
||||||
|
ao2_unlink(types[idx]->internal->opts, opt);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int aco_option_register_deprecated(struct aco_info *info, const char *name, struct aco_type **types, const char *aliased_to)
|
||||||
|
{
|
||||||
|
struct aco_option *opt;
|
||||||
|
|
||||||
|
if (!info || ast_strlen_zero(name) || ast_strlen_zero(aliased_to)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(opt = ao2_alloc(sizeof(*opt), config_option_destroy))) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
opt->name = name;
|
||||||
|
opt->aliased_to = aliased_to;
|
||||||
|
opt->deprecated = 1;
|
||||||
|
opt->match_type = ACO_EXACT;
|
||||||
|
|
||||||
|
if (link_option_to_types(types, opt)) {
|
||||||
|
ao2_ref(opt, -1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int __aco_option_register(struct aco_info *info, const char *name, enum aco_matchtype matchtype, struct aco_type **types,
|
int __aco_option_register(struct aco_info *info, const char *name, enum aco_matchtype matchtype, struct aco_type **types,
|
||||||
const char *default_val, enum aco_option_type kind, aco_option_handler handler, unsigned int flags, size_t argc, ...)
|
const char *default_val, enum aco_option_type kind, aco_option_handler handler, unsigned int flags, size_t argc, ...)
|
||||||
{
|
{
|
||||||
struct aco_option *opt;
|
struct aco_option *opt;
|
||||||
struct aco_type *type;
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int tmp;
|
int tmp;
|
||||||
|
|
||||||
@@ -183,16 +225,10 @@ int __aco_option_register(struct aco_info *info, const char *name, enum aco_matc
|
|||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
tmp = 0;
|
if (link_option_to_types(types, opt)) {
|
||||||
while ((type = types[tmp++])) {
|
|
||||||
if (!ao2_link(type->internal->opts, opt)) {
|
|
||||||
while (--tmp) {
|
|
||||||
ao2_unlink(types[tmp]->internal->opts, opt);
|
|
||||||
}
|
|
||||||
ao2_ref(opt, -1);
|
ao2_ref(opt, -1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -501,10 +537,18 @@ int aco_process_category_options(struct aco_type *type, struct ast_config *cfg,
|
|||||||
|
|
||||||
for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
|
for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
|
||||||
RAII_VAR(struct aco_option *, opt, aco_option_find(type, var->name), ao2_cleanup);
|
RAII_VAR(struct aco_option *, opt, aco_option_find(type, var->name), ao2_cleanup);
|
||||||
|
if (opt && opt->deprecated && !ast_strlen_zero(opt->aliased_to)) {
|
||||||
|
const char *alias = ast_strdupa(opt->aliased_to);
|
||||||
|
ast_log(LOG_WARNING, "At line %d of %s option '%s' is deprecated. Use '%s' instead\n", var->lineno, var->file, var->name, alias);
|
||||||
|
ao2_ref(opt, -1);
|
||||||
|
opt = aco_option_find(type, alias);
|
||||||
|
}
|
||||||
|
|
||||||
if (!opt) {
|
if (!opt) {
|
||||||
ast_log(LOG_ERROR, "Could not find option suitable for category '%s' named '%s' at line %d of %s\n", cat, var->name, var->lineno, var->file);
|
ast_log(LOG_ERROR, "Could not find option suitable for category '%s' named '%s' at line %d of %s\n", cat, var->name, var->lineno, var->file);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opt->handler) {
|
if (!opt->handler) {
|
||||||
/* It should be impossible for an option to not have a handler */
|
/* It should be impossible for an option to not have a handler */
|
||||||
ast_log(LOG_ERROR, "BUG! Somehow a config option for %s/%s was created with no handler!\n", cat, var->name);
|
ast_log(LOG_ERROR, "BUG! Somehow a config option for %s/%s was created with no handler!\n", cat, var->name);
|
||||||
|
@@ -824,6 +824,8 @@ AST_TEST_DEFINE(config_options_test)
|
|||||||
aco_option_register(&cfg_info, "codecopt", ACO_EXACT, config_test_conf.types, CODEC_DEFAULT, OPT_CODEC_T, 1, FLDSET(struct test_item, codecprefopt, codeccapopt));
|
aco_option_register(&cfg_info, "codecopt", ACO_EXACT, config_test_conf.types, CODEC_DEFAULT, OPT_CODEC_T, 1, FLDSET(struct test_item, codecprefopt, codeccapopt));
|
||||||
aco_option_register(&cfg_info, "stropt", ACO_EXACT, config_test_conf.types, STR_DEFAULT, OPT_STRINGFIELD_T, 0, STRFLDSET(struct test_item, stropt));
|
aco_option_register(&cfg_info, "stropt", ACO_EXACT, config_test_conf.types, STR_DEFAULT, OPT_STRINGFIELD_T, 0, STRFLDSET(struct test_item, stropt));
|
||||||
aco_option_register_custom(&cfg_info, "customopt", ACO_EXACT, config_test_conf.types, CUSTOM_DEFAULT, customopt_handler, 0);
|
aco_option_register_custom(&cfg_info, "customopt", ACO_EXACT, config_test_conf.types, CUSTOM_DEFAULT, customopt_handler, 0);
|
||||||
|
aco_option_register_deprecated(&cfg_info, "permit", config_test_conf.types, "aclpermitopt");
|
||||||
|
aco_option_register_deprecated(&cfg_info, "deny", config_test_conf.types, "acldenyopt");
|
||||||
|
|
||||||
if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
|
if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
|
||||||
ast_test_status_update(test, "Could not parse config\n");
|
ast_test_status_update(test, "Could not parse config\n");
|
||||||
|
Reference in New Issue
Block a user