From: Alan T. DeKok Date: Wed, 26 Nov 2025 20:06:25 +0000 (-0500) Subject: add recursive option for printing dictionary entries X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=373eb3aead6c71bacd3ae2f49ef4dd71e15327e2;p=thirdparty%2Ffreeradius-server.git add recursive option for printing dictionary entries --- diff --git a/src/bin/radict.c b/src/bin/radict.c index 03a0fca1a53..e44d2b7d15b 100644 --- a/src/bin/radict.c +++ b/src/bin/radict.c @@ -45,6 +45,7 @@ typedef enum { static fr_dict_t *dicts[255]; static bool print_values = false; static bool print_headers = false; +static bool print_recursive = false; static radict_out_t output_format = RADICT_OUT_FANCY; static fr_dict_t **dict_end = dicts; @@ -65,6 +66,7 @@ static void usage(void) fprintf(stderr, " -h Print help text.\n"); fprintf(stderr, " -H Show the headers of each field.\n"); fprintf(stderr, " -p Set protocol by name\n"); + fprintf(stderr, " -r Write out attributes recursively.\n"); fprintf(stderr, " -V Write out all attribute values.\n"); fprintf(stderr, " -x Debugging mode.\n"); fprintf(stderr, "\n"); @@ -162,15 +164,21 @@ static int load_dicts(char const *dict_dir, char const *protocol) return 0; } -static void da_print_info_td(fr_dict_t const *dict, fr_dict_attr_t const *da) +static const char *spaces = " "; + +static void da_print_info_td(fr_dict_t const *dict, fr_dict_attr_t const *da, int depth) { char oid_str[512]; char flags[256]; fr_hash_iter_t iter; - fr_dict_enum_value_t *enumv; + fr_dict_enum_value_t *enumv; fr_sbuff_t old_str_sbuff = FR_SBUFF_OUT(oid_str, sizeof(oid_str)); fr_sbuff_t flags_sbuff = FR_SBUFF_OUT(flags, sizeof(flags)); + char const *type; + fr_dict_attr_t const *child; + fr_hash_table_t *namespace; + if (fr_dict_attr_oid_print(&old_str_sbuff, NULL, da, false) <= 0) { fr_strerror_printf("OID string too long"); fr_exit(EXIT_FAILURE); @@ -178,6 +186,15 @@ static void da_print_info_td(fr_dict_t const *dict, fr_dict_attr_t const *da) fr_dict_attr_flags_print(&flags_sbuff, dict, da->type, &da->flags); + if (!da->flags.is_alias) { + type = fr_type_to_str(da->type); + } else { + fr_assert(da->type == FR_TYPE_VOID); + type = "ALIAS"; + } + + printf("%.*s", depth, spaces); + /* Protocol Name Type */ switch(output_format) { @@ -187,7 +204,7 @@ static void da_print_info_td(fr_dict_t const *dict, fr_dict_attr_t const *da) fr_sbuff_start(&old_str_sbuff), da->name, da->attr, - fr_type_to_str(da->type), + type, fr_sbuff_start(&flags_sbuff)); break; @@ -198,7 +215,7 @@ static void da_print_info_td(fr_dict_t const *dict, fr_dict_attr_t const *da) fr_sbuff_start(&old_str_sbuff), da->name, da->attr, - fr_type_to_str(da->type), + type, fr_sbuff_start(&flags_sbuff)); } @@ -213,7 +230,6 @@ static void da_print_info_td(fr_dict_t const *dict, fr_dict_attr_t const *da) enumv = fr_hash_table_iter_next(ext->value_by_name, &iter)) { char *str; - switch(output_format) { case RADICT_OUT_CSV: str = fr_asprintf(NULL, "%s,%s,%s,%d,%s,%s,%s,%pV", @@ -221,7 +237,7 @@ static void da_print_info_td(fr_dict_t const *dict, fr_dict_attr_t const *da) fr_sbuff_start(&old_str_sbuff), da->name, da->attr, - fr_type_to_str(da->type), + type, fr_sbuff_start(&flags_sbuff), enumv->name, enumv->value); @@ -234,16 +250,30 @@ static void da_print_info_td(fr_dict_t const *dict, fr_dict_attr_t const *da) fr_sbuff_start(&old_str_sbuff), da->name, da->attr, - fr_type_to_str(da->type), + type, fr_sbuff_start(&flags_sbuff), enumv->name, enumv->value); } - printf("%s\n", str); + printf("%.*s%s\n", depth, spaces, str); talloc_free(str); } } + + /* + * Print definitions recursively. + */ + if (!print_recursive || !fr_type_is_structural(da->type)) return; + + namespace = dict_attr_namespace(da); + fr_assert(namespace != NULL); + + for (child = fr_hash_table_iter_init(namespace, &iter); + child != NULL; + child = fr_hash_table_iter_next(namespace, &iter)) { + da_print_info_td(dict, child, depth + 1); + } } static void _raddict_export(fr_dict_t const *dict, uint64_t *count, uintptr_t *low, uintptr_t *high, fr_dict_attr_t const *da, unsigned int lvl) @@ -268,7 +298,7 @@ static void _raddict_export(fr_dict_t const *dict, uint64_t *count, uintptr_t *l *high = (uintptr_t)da; } - da_print_info_td(fr_dict_by_da(da), da); + da_print_info_td(fr_dict_by_da(da), da, 0); } if (count) (*count)++; @@ -332,7 +362,7 @@ int main(int argc, char *argv[]) fr_debug_lvl = 1; fr_log_fp = stdout; - while ((c = getopt(argc, argv, "AcfED:p:VxhH")) != -1) switch (c) { + while ((c = getopt(argc, argv, "AcfED:p:rVxhH")) != -1) switch (c) { case 'A': alias = true; break; @@ -361,6 +391,10 @@ int main(int argc, char *argv[]) protocol = optarg; break; + case 'r': + print_recursive = true; + break; + case 'V': print_values = true; break; @@ -449,6 +483,8 @@ int main(int argc, char *argv[]) DEBUG2("Memory allocd %zu (bytes)", talloc_total_size(*dict_p)); DEBUG2("Memory spread %zu (bytes)", (size_t) (high - low)); } while (++dict_p < dict_end); + + goto finish; } if (alias) { @@ -459,6 +495,8 @@ int main(int argc, char *argv[]) fr_dict_alias_export(fr_log_fp, fr_dict_root(*dict_p)); } } while (++dict_p < dict_end); + + goto finish; } if (argc == 0) { @@ -482,7 +520,7 @@ int main(int argc, char *argv[]) da = fr_dict_attr_by_oid(NULL, fr_dict_root(*dict_p), attr); if (da) { - da_print_info_td(*dict_p, da); + da_print_info_td(*dict_p, da, 0); found = true; } else { fprintf(stderr, "Dictionary %s does not contain attribute %s\n",