📄 conffile.c
字号:
if (pair == NULL){ return cf_pair_find(cs, attr); } ci = cf_pairtoitem(pair)->next; for (; ci; ci = ci->next) { if (ci->type != CONF_ITEM_PAIR) continue; if (attr == NULL || strcmp(cf_itemtopair(ci)->attr, attr) == 0) break; } return cf_itemtopair(ci);}/* * Find a CONF_SECTION, or return the root if name is NULL */CONF_SECTION *cf_section_find(const char *name){ if (name) return cf_section_sub_find(mainconfig.config, name); else return mainconfig.config;}/* * Find a sub-section in a section */CONF_SECTION *cf_section_sub_find(const CONF_SECTION *cs, const char *name){ CONF_ITEM *ci; /* * Do the fast lookup if possible. */ if (name && cs->section_tree) { CONF_SECTION mycs; mycs.name1 = name; mycs.name2 = NULL; return rbtree_finddata(cs->section_tree, &mycs); } for (ci = cs->children; ci; ci = ci->next) { if (ci->type != CONF_ITEM_SECTION) continue; if (strcmp(cf_itemtosection(ci)->name1, name) == 0) break; } return cf_itemtosection(ci);}/* * Find a CONF_SECTION with both names. */CONF_SECTION *cf_section_sub_find_name2(const CONF_SECTION *cs, const char *name1, const char *name2){ CONF_ITEM *ci; if (!cs) cs = mainconfig.config; if (name1 && (cs->section_tree)) { CONF_SECTION mycs, *master_cs; mycs.name1 = name1; mycs.name2 = name2; master_cs = rbtree_finddata(cs->section_tree, &mycs); if (master_cs) { return rbtree_finddata(master_cs->name2_tree, &mycs); } } /* * Else do it the old-fashioned way. */ for (ci = cs->children; ci; ci = ci->next) { CONF_SECTION *subcs; if (ci->type != CONF_ITEM_SECTION) continue; subcs = cf_itemtosection(ci); if (!name1) { if (!subcs->name2) { if (strcmp(subcs->name1, name2) == 0) break; } else { if (strcmp(subcs->name2, name2) == 0) break; } continue; /* don't do the string comparisons below */ } if ((strcmp(subcs->name1, name1) == 0) && (subcs->name2 != NULL) && (strcmp(subcs->name2, name2) == 0)) break; } return cf_itemtosection(ci);}/* * Return the next subsection after a CONF_SECTION * with a certain name1 (char *name1). If the requested * name1 is NULL, any name1 matches. */CONF_SECTION *cf_subsection_find_next(CONF_SECTION *section, CONF_SECTION *subsection, const char *name1){ CONF_ITEM *ci; /* * If subsection is NULL this must be a first time run * Find the subsection with correct name */ if (subsection == NULL){ ci = section->children; } else { ci = cf_sectiontoitem(subsection)->next; } for (; ci; ci = ci->next) { if (ci->type != CONF_ITEM_SECTION) continue; if ((name1 == NULL) || (strcmp(cf_itemtosection(ci)->name1, name1) == 0)) break; } return cf_itemtosection(ci);}/* * Return the next section after a CONF_SECTION * with a certain name1 (char *name1). If the requested * name1 is NULL, any name1 matches. */CONF_SECTION *cf_section_find_next(CONF_SECTION *section, CONF_SECTION *subsection, const char *name1){ if (!section->item.parent) return NULL; return cf_subsection_find_next(section->item.parent, subsection, name1);}/* * Return the next item after a CONF_ITEM. */CONF_ITEM *cf_item_find_next(CONF_SECTION *section, CONF_ITEM *item){ /* * If item is NULL this must be a first time run * Return the first item */ if (item == NULL) { return section->children; } else { return item->next; }}int cf_section_lineno(CONF_SECTION *section){ return cf_sectiontoitem(section)->lineno;}const char *cf_pair_filename(CONF_PAIR *pair){ return cf_pairtoitem(pair)->filename;}const char *cf_section_filename(CONF_SECTION *section){ return cf_sectiontoitem(section)->filename;}int cf_pair_lineno(CONF_PAIR *pair){ return cf_pairtoitem(pair)->lineno;}int cf_item_is_section(CONF_ITEM *item){ return item->type == CONF_ITEM_SECTION;}int cf_item_is_pair(CONF_ITEM *item){ return item->type == CONF_ITEM_PAIR;}static CONF_DATA *cf_data_alloc(CONF_SECTION *parent, const char *name, void *data, void (*data_free)(void *)){ char *p; size_t name_len; CONF_DATA *cd; name_len = strlen(name) + 1; p = rad_malloc(sizeof(*cd) + name_len); cd = (CONF_DATA *) p; memset(cd, 0, sizeof(*cd)); cd->item.type = CONF_ITEM_DATA; cd->item.parent = parent; cd->data = data; cd->free = data_free; p += sizeof(*cd); memcpy(p, name, name_len); cd->name = p; return cd;}static void *cf_data_find_internal(CONF_SECTION *cs, const char *name, int flag){ if (!cs || !name) return NULL; /* * Find the name in the tree, for speed. */ if (cs->data_tree) { CONF_DATA mycd; mycd.name = name; mycd.flag = flag; return rbtree_finddata(cs->data_tree, &mycd); } return NULL;}/* * Find data from a particular section. */void *cf_data_find(CONF_SECTION *cs, const char *name){ CONF_DATA *cd = cf_data_find_internal(cs, name, 0); if (cd) return cd->data; return NULL;}/* * Add named data to a configuration section. */static int cf_data_add_internal(CONF_SECTION *cs, const char *name, void *data, void (*data_free)(void *), int flag){ CONF_DATA *cd; if (!cs || !name) return -1; /* * Already exists. Can't add it. */ if (cf_data_find_internal(cs, name, flag) != NULL) return -1; cd = cf_data_alloc(cs, name, data, data_free); if (!cd) return -1; cd->flag = flag; cf_item_add(cs, cf_datatoitem(cd)); return 0;}/* * Add named data to a configuration section. */int cf_data_add(CONF_SECTION *cs, const char *name, void *data, void (*data_free)(void *)){ return cf_data_add_internal(cs, name, data, data_free, 0);}#if 0/* * Copy CONF_DATA from src to dst */static void cf_section_copy_data(CONF_SECTION *s, CONF_SECTION *d){ CONF_ITEM *cd, *next, **last; /* * Don't check if s->data_tree is NULL. It's child * sections may have data, even if this section doesn't. */ rad_assert(d->data_tree == NULL); d->data_tree = s->data_tree; s->data_tree = NULL; /* * Walk through src, moving CONF_ITEM_DATA * to dst, by hand. */ last = &(s->children); for (cd = s->children; cd != NULL; cd = next) { next = cd->next; /* * Recursively copy data from child sections. */ if (cd->type == CONF_ITEM_SECTION) { CONF_SECTION *s1, *d1; s1 = cf_itemtosection(cd); d1 = cf_section_sub_find_name2(d, s1->name1, s1->name2); if (d1) { cf_section_copy_data(s1, d1); } last = &(cd->next); continue; } /* * Not conf data, remember last ptr. */ if (cd->type != CONF_ITEM_DATA) { last = &(cd->next); continue; } /* * Remove it from the src list */ *last = cd->next; cd->next = NULL; /* * Add it to the dst list */ if (!d->children) { rad_assert(d->tail == NULL); d->children = cd; } else { rad_assert(d->tail != NULL); d->tail->next = cd; } d->tail = cd; }}/* * For a CONF_DATA element, stat the filename, if necessary. */static int filename_stat(void *context, void *data){ struct stat buf; CONF_DATA *cd = data; context = context; /* -Wunused */ if (cd->flag != PW_TYPE_FILENAME) return 0; if (stat(cd->name, &buf) < 0) return -1; if (buf.st_mtime != *(time_t *) cd->data) return -1; return 0;}/* * Compare two CONF_SECTIONS. The items MUST be in the same * order. */static int cf_section_cmp(CONF_SECTION *a, CONF_SECTION *b){ CONF_ITEM *ca = a->children; CONF_ITEM *cb = b->children; while (1) { CONF_PAIR *pa, *pb; /* * Done. Stop. */ if (!ca && !cb) break; /* * Skip CONF_DATA. */ if (ca && ca->type == CONF_ITEM_DATA) { ca = ca->next; continue; } if (cb && cb->type == CONF_ITEM_DATA) { cb = cb->next; continue; } /* * One is smaller than the other. Exit. */ if (!ca || !cb) return 0; if (ca->type != cb->type) return 0; /* * Deal with subsections. */ if (ca->type == CONF_ITEM_SECTION) { CONF_SECTION *sa = cf_itemtosection(ca); CONF_SECTION *sb = cf_itemtosection(cb); if (!cf_section_cmp(sa, sb)) return 0; goto next; } rad_assert(ca->type == CONF_ITEM_PAIR); pa = cf_itemtopair(ca); pb = cf_itemtopair(cb); /* * Different attr and/or value, Exit. */ if ((strcmp(pa->attr, pb->attr) != 0) || (strcmp(pa->value, pb->value) != 0)) return 0; /* * And go to the next element. */ next: ca = ca->next; cb = cb->next; } /* * Walk over the CONF_DATA, stat'ing PW_TYPE_FILENAME. */ if (a->data_tree && (rbtree_walk(a->data_tree, InOrder, filename_stat, NULL) != 0)) { return 0; } /* * They must be the same, say so. */ return 1;}/* * Migrate CONF_DATA from one section to another. */int cf_section_migrate(CONF_SECTION *dst, CONF_SECTION *src){ CONF_ITEM *ci; CONF_SECTION *s, *d; for (ci = src->children; ci != NULL; ci = ci->next) { if (ci->type != CONF_ITEM_SECTION) continue; s = cf_itemtosection(ci); d = cf_section_sub_find_name2(dst, s->name1, s->name2); if (!d) continue; /* not in new one, don't migrate it */ /* * A section of the same name is in BOTH src & dst, * compare the CONF_PAIR's. If they're all the same, * then copy the CONF_DATA from one to the other. */ if (cf_section_cmp(s, d)) { cf_section_copy_data(s, d); } } return 1; /* rcode means anything? */}#endifint cf_section_template(CONF_SECTION *cs, CONF_SECTION *template){ if (!cs || !template || cs->template || template->template) return -1; cs->template = template; return 0;}/* * This is here to make the rest of the code easier to read. It * ties conffile.c to log.c, but it means we don't have to * pollute every other function with the knowledge of the * configuration internals. */void cf_log_err(CONF_ITEM *ci, const char *fmt, ...){ va_list ap; char buffer[256]; va_start(ap, fmt); vsnprintf(buffer, sizeof(buffer), fmt, ap); va_end(ap); radlog(L_ERR, "%s[%d]: %s", ci->filename, ci->lineno, buffer);}void cf_log_info(UNUSED CONF_SECTION *cs, const char *fmt, ...){ va_list ap; va_start(ap, fmt); if (debug_flag > 1 && cf_log_config) vradlog(L_DBG, fmt, ap); va_end(ap);}/* * Wrapper to simplify the code. */void cf_log_module(UNUSED CONF_SECTION *cs, const char *fmt, ...){ va_list ap; char buffer[256]; va_start(ap, fmt); if (debug_flag > 1 && cf_log_modules) { vsnprintf(buffer, sizeof(buffer), fmt, ap); radlog(L_DBG, " Module: %s", buffer); } va_end(ap);}#if 0/* * JMG dump_config tries to dump the config structure in a readable format **/static int dump_config_section(CONF_SECTION *cs, int indent){ CONF_SECTION *scs; CONF_PAIR *cp; CONF_ITEM *ci; /* The DEBUG macro doesn't let me * for(i=0;i<indent;++i) debugputchar('\t'); * so I had to get creative. --Pac. */ for (ci = cs->children; ci; ci = ci->next) { switch (ci->type) { case CONF_ITEM_PAIR: cp=cf_itemtopair(ci); DEBUG("%.*s%s = %s", indent, "\t\t\t\t\t\t\t\t\t\t\t", cp->attr, cp->value); break; case CONF_ITEM_SECTION: scs=cf_itemtosection(ci); DEBUG("%.*s%s %s%s{", indent, "\t\t\t\t\t\t\t\t\t\t\t", scs->name1, scs->name2 ? scs->name2 : "", scs->name2 ? " " : ""); dump_config_section(scs, indent+1); DEBUG("%.*s}", indent, "\t\t\t\t\t\t\t\t\t\t\t"); break; default: /* FIXME: Do more! */ break; } } return 0;}int dump_config(CONF_SECTION *cs){ return dump_config_section(cs, 0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -