📄 conffile.c
字号:
variables[i].name, value, ip_ntoa(buffer, ipaddr)); *(uint32_t *) data = ipaddr; break; default: radlog(L_ERR, "type %d not supported yet", variables[i].type); return -1; break; } /* switch over variable type */ } /* for all variables in the configuration section */ return 0;}/* * Read a part of the config file. */static CONF_SECTION *cf_section_read(const char *cf, int *lineno, FILE *fp, const char *name1, const char *name2, CONF_SECTION *parent){ CONF_SECTION *cs, *css; CONF_PAIR *cpn; char *ptr; const char *value; char buf[8192]; char buf1[8192]; char buf2[8192]; char buf3[8192]; int t1, t2, t3; char *cbuf = buf; int len; /* * Ensure that the user can't add CONF_SECTIONs * with 'internal' names; */ if ((name1 != NULL) && (name1[0] == '_')) { radlog(L_ERR, "%s[%d]: Illegal configuration section name", cf, *lineno); return NULL; } /* * Allocate new section. */ cs = cf_section_alloc(name1, name2, parent); cs->item.lineno = *lineno; /* * Read, checking for line continuations ('\\' at EOL) */ for (;;) { int eof; /* * Get data, and remember if we are at EOF. */ eof = (fgets(cbuf, sizeof(buf) - (cbuf - buf), fp) == NULL); (*lineno)++; len = strlen(cbuf); /* * We've filled the buffer, and there isn't * a CR in it. Die! */ if ((len == sizeof(buf)) && (cbuf[len - 1] != '\n')) { radlog(L_ERR, "%s[%d]: Line too long", cf, *lineno); cf_section_free(&cs); return NULL; } /* * Check for continuations. */ if (cbuf[len - 1] == '\n') len--; /* * Last character is '\\'. Over-write it, * and read another line. */ if ((len > 0) && (cbuf[len - 1] == '\\')) { cbuf[len - 1] = '\0'; cbuf += len - 1; continue; } /* * We're at EOF, and haven't read anything. Stop. */ if (eof && (cbuf == buf)) { break; } ptr = cbuf = buf; t1 = gettoken(&ptr, buf1, sizeof(buf1)); /* * Skip comments and blank lines immediately. */ if ((*buf1 == '#') || (*buf1 == '\0')) { continue; } /* * Allow for $INCLUDE files * * This *SHOULD* work for any level include. * I really really really hate this file. -cparker */ if (strcasecmp(buf1, "$INCLUDE") == 0) { CONF_SECTION *is; t2 = getword(&ptr, buf2, sizeof(buf2)); value = cf_expand_variables(cf, lineno, cs, buf, buf2); if (value == NULL) { cf_section_free(&cs); return NULL; } DEBUG2( "Config: including file: %s", value ); if ((is = conf_read(cf, *lineno, value, parent)) == NULL) { cf_section_free(&cs); return NULL; } /* * Add the included conf to our CONF_SECTION */ if (is != NULL) { if (is->children != NULL) { CONF_ITEM *ci; /* * Re-write the parent of the * moved children to be the * upper-layer section. */ for (ci = is->children; ci; ci = ci->next) { ci->parent = cs; } /* * If there are children, then * move them up a layer. */ if (is->children) { cf_item_add(cs, is->children); } is->children = NULL; } /* * Always free the section for the * $INCLUDEd file. */ cf_section_free(&is); } continue; } /* * No '=': must be a section or sub-section. */ if (strchr(ptr, '=') == NULL) { t2 = gettoken(&ptr, buf2, sizeof(buf2)); t3 = gettoken(&ptr, buf3, sizeof(buf3)); } else { t2 = gettoken(&ptr, buf2, sizeof(buf2)); t3 = getword(&ptr, buf3, sizeof(buf3)); } /* * See if it's the end of a section. */ if (t1 == T_RCBRACE) { if (name1 == NULL || buf2[0]) { radlog(L_ERR, "%s[%d]: Unexpected end of section", cf, *lineno); cf_section_free(&cs); return NULL; } return cs; } /* * Perhaps a subsection. */ if (t2 == T_LCBRACE || t3 == T_LCBRACE) { css = cf_section_read(cf, lineno, fp, buf1, t2==T_LCBRACE ? NULL : buf2, cs); if (css == NULL) { cf_section_free(&cs); return NULL; } cf_item_add(cs, cf_sectiontoitem(css)); continue; } /* * Ignore semi-colons. */ if (*buf2 == ';') *buf2 = '\0'; /* * Must be a normal attr = value line. */ if (buf1[0] != 0 && buf2[0] == 0 && buf3[0] == 0) { t2 = T_OP_EQ; } else if (buf1[0] == 0 || buf2[0] == 0 || (t2 < T_EQSTART || t2 > T_EQEND)) { radlog(L_ERR, "%s[%d]: Line is not in 'attribute = value' format", cf, *lineno); cf_section_free(&cs); return NULL; } /* * Ensure that the user can't add CONF_PAIRs * with 'internal' names; */ if (buf1[0] == '_') { radlog(L_ERR, "%s[%d]: Illegal configuration pair name \"%s\"", cf, *lineno, buf1); cf_section_free(&cs); return NULL; } /* * Handle variable substitution via ${foo} */ value = cf_expand_variables(cf, lineno, cs, buf, buf3); if (!value) { cf_section_free(&cs); return NULL; } /* * Add this CONF_PAIR to our CONF_SECTION */ cpn = cf_pair_alloc(buf1, value, t2, parent); cpn->item.lineno = *lineno; cf_item_add(cs, cf_pairtoitem(cpn)); } /* * See if EOF was unexpected .. */ if (name1 != NULL) { radlog(L_ERR, "%s[%d]: Unexpected end of file", cf, *lineno); cf_section_free(&cs); return NULL; } return cs;}/* * Read the config file. */CONF_SECTION *conf_read(const char *fromfile, int fromline, const char *conffile, CONF_SECTION *parent){ FILE *fp; int lineno = 0; CONF_SECTION *cs; if ((fp = fopen(conffile, "r")) == NULL) { if (fromfile) { radlog(L_ERR|L_CONS, "%s[%d]: Unable to open file \"%s\": %s", fromfile, fromline, conffile, strerror(errno)); } else { radlog(L_ERR|L_CONS, "Unable to open file \"%s\": %s", conffile, strerror(errno)); } return NULL; } if(parent) { cs = cf_section_read(conffile, &lineno, fp, NULL, NULL, parent); } else { cs = cf_section_read(conffile, &lineno, fp, NULL, NULL, NULL); } fclose(fp); return cs;}/* * Return a CONF_PAIR within a CONF_SECTION. */CONF_PAIR *cf_pair_find(CONF_SECTION *section, const char *name){ CONF_ITEM *ci; if (section == NULL) { section = mainconfig.config; } for (ci = section->children; ci; ci = ci->next) { if (ci->type != CONF_ITEM_PAIR) continue; if (name == NULL || strcmp(cf_itemtopair(ci)->attr, name) == 0) break; } return cf_itemtopair(ci);}/* * Return the attr of a CONF_PAIR */char *cf_pair_attr(CONF_PAIR *pair){ return (pair ? pair->attr : NULL);}/* * Return the value of a CONF_PAIR */char *cf_pair_value(CONF_PAIR *pair){ return (pair ? pair->value : NULL);}/* * Return the first label of a CONF_SECTION */char *cf_section_name1(CONF_SECTION *section){ return (section ? section->name1 : NULL);}/* * Return the second label of a CONF_SECTION */char *cf_section_name2(CONF_SECTION *section){ return (section ? section->name2 : NULL);}/* * Find a value in a CONF_SECTION */char *cf_section_value_find(CONF_SECTION *section, const char *attr){ CONF_PAIR *cp; cp = cf_pair_find(section, attr); return (cp ? cp->value : NULL);}/* * Return the next pair after a CONF_PAIR * with a certain name (char *attr) If the requested * attr is NULL, any attr matches. */CONF_PAIR *cf_pair_find_next(CONF_SECTION *section, CONF_PAIR *pair, const char *attr){ CONF_ITEM *ci; /* * If pair is NULL this must be a first time run * Find the pair with correct name */ if (pair == NULL){ return cf_pair_find(section, 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(CONF_SECTION *section, const char *name){ CONF_ITEM *ci; for (ci = section->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);}/* * 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 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;}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;}#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) { if (ci->type == 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); } else { 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"); } } return 0;}int dump_config(void){ return dump_config_section(mainconfig.config, 0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -