📄 dict.c
字号:
librad_log("dict_init: %s[%d]: invalid value", fn, line); return -1; } if (valstr[0] != '0') value = atoi(valstr); else sscanf(valstr, "%i", &value); if (dict_addvalue(namestr, attrstr, value) < 0) { librad_log("dict_init: %s[%d]: %s", fn, line, librad_errstr); return -1; } return 0;}/* * Process the VENDOR command */static int process_vendor(const char* fn, const int line, const char* data){ char valstr[256]; char attrstr[256]; int value; if (sscanf(data, "%s%s", attrstr, valstr) != 2) { librad_log( "dict_init: %s[%d] invalid VENDOR entry", fn, line); return -1; } /* * Validate all entries */ if (!isdigit((int) *valstr)) { librad_log("dict_init: %s[%d]: invalid value", fn, line); return -1; } value = atoi(valstr); /* Create a new VENDOR entry for the list */ if (dict_addvendor(attrstr, value) < 0) { librad_log("dict_init: %s[%d]: %s", fn, line, librad_errstr); return -1; } return 0;}/* * Initialize the dictionary. */static int my_dict_init(const char *dir, const char *fn, const char *src_file, int src_line){ FILE *fp; char dirtmp[256]; char buf[256]; char optstr[256]; char *p; char *keyword; char *data; int line = 0; int vendor; int block_vendor; if (strlen(fn) >= sizeof(dirtmp) / 2 || strlen(dir) >= sizeof(dirtmp) / 2) { librad_log("dict_init: filename name too long"); return -1; } /* * First see if fn is relative to dir. If so, create * new filename. If not, remember the absolute dir. */ if ((p = strrchr(fn, '/')) != NULL) { strcpy(dirtmp, fn); dirtmp[p - fn] = 0; dir = dirtmp; } else if (dir && dir[0] && strcmp(dir, ".") != 0) { snprintf(dirtmp, sizeof(dirtmp), "%s/%s", dir, fn); fn = dirtmp; } if ((fp = fopen(fn, "r")) == NULL) { if (!src_file) { librad_log("dict_init: Couldn't open dictionary \"%s\": %s", fn, strerror(errno)); } else { librad_log("dict_init: %s[%d]: Couldn't open dictionary \"%s\": %s", src_file, src_line, fn, strerror(errno)); } return -1; } block_vendor = 0; while (fgets(buf, sizeof(buf), fp) != NULL) { line++; if (buf[0] == '#' || buf[0] == 0 || buf[0] == '\n' || buf[0] == '\r') continue; /* * Comment characters should NOT be appearing anywhere but * as start of a comment; */ p = strchr(buf, '#'); if (p) *p = '\0'; keyword = strtok(buf, " \t\r\n"); if (keyword == NULL) { continue; } data = strtok(NULL, "\r\n"); if (data == NULL || data[0] == 0) { librad_log("dict_init: %s[%d]: invalid entry for keyword %s", fn, line, keyword); fclose(fp); return -1; } /* * See if we need to import another dictionary. */ if (strcasecmp(keyword, "$INCLUDE") == 0) { p = strtok(data, " \t"); if (my_dict_init(dir, data, fn, line) < 0) { fclose(fp); return -1; } continue; } /* $INCLUDE */ /* * Perhaps this is an attribute. */ if (strcasecmp(keyword, "ATTRIBUTE") == 0) { if (process_attribute(fn, line, block_vendor, data) == -1) { fclose(fp); return -1; } continue; } /* * Process VALUE lines. */ if (strcasecmp(keyword, "VALUE") == 0) { if (process_value(fn, line, data) == -1) { fclose(fp); return -1; } continue; } /* * Process VENDOR lines. */ if (strcasecmp(keyword, "VENDOR") == 0) { if (process_vendor(fn, line, data) == -1) { fclose(fp); return -1; } continue; } if (strcasecmp(keyword, "BEGIN-VENDOR") == 0) { optstr[0] = 0; if (sscanf(data, "%s", optstr) != 1) { librad_log( "dict_init: %s[%d] invalid BEGIN-VENDOR entry", fn, line); fclose(fp); return -1; } vendor = dict_vendorbyname(optstr); if (!vendor) { librad_log( "dict_init: %s[%d]: unknown vendor %s", fn, line, optstr); fclose(fp); return -1; } block_vendor = vendor; continue; } /* BEGIN-VENDOR */ if (strcasecmp(keyword, "END-VENDOR") == 0) { optstr[0] = 0; if (sscanf(data, "%s", optstr) != 1) { librad_log( "dict_init: %s[%d] invalid END-VENDOR entry", fn, line); fclose(fp); return -1; } vendor = dict_vendorbyname(optstr); if (!vendor) { librad_log( "dict_init: %s[%d]: unknown vendor %s", fn, line, optstr); fclose(fp); return -1; } if (vendor != block_vendor) { librad_log( "dict_init: %s[%d]: END-VENDOR %s does not match any previous BEGIN-VENDOR", fn, line, optstr); fclose(fp); return -1; } block_vendor = 0; continue; } /* END-VENDOR */ /* * Any other string: We don't recognize it. */ librad_log( "dict_init: %s[%d] invalid keyword \"%s\"", fn, line, keyword); fclose(fp); return -1; } fclose(fp); return 0;}/* * Callbacks for red-black trees. */static int attrname_cmp(const void *a, const void *b){ return strcasecmp(((const DICT_ATTR *)a)->name, ((const DICT_ATTR *)b)->name);}/* * Return: < 0 if a < b, * == 0 if a == b */static int attrvalue_cmp(const void *a, const void *b){ return (((const DICT_ATTR *)a)->attr - ((const DICT_ATTR *)b)->attr);}/* * Compare values by name, keying off of the attribute number, * and then the value name. */static int valuename_cmp(const void *a, const void *b){ int rcode; rcode = (((const DICT_VALUE *)a)->attr - ((const DICT_VALUE *)b)->attr); if (rcode != 0) return rcode;return strcasecmp(((const DICT_VALUE *)a)->name, ((const DICT_VALUE *)b)->name);}/* * Compare values by value, keying off of the attribute number, * and then the value number. */static int valuevalue_cmp(const void *a, const void *b){ int rcode; rcode = (((const DICT_VALUE *)a)->attr - ((const DICT_VALUE *)b)->attr); if (rcode != 0) return rcode; return (((const DICT_VALUE *)a)->value - ((const DICT_VALUE *)b)->value);}/* * Initialize the directory, then fix the attr member of * all attributes. */int dict_init(const char *dir, const char *fn){ dict_free(); /* * Create the tree of attributes by name. There MAY NOT * be multiple attributes of the same name. * * Each attribute is malloc'd, so the free function is free. */ attributes_byname = rbtree_create(attrname_cmp, free, 0); if (!attributes_byname) { return -1; } /* * Create the tree of attributes by value. There MAY * be attributes of the same value. If there are, we * pick the latest one. */ attributes_byvalue = rbtree_create(attrvalue_cmp, NULL, 1); if (!attributes_byvalue) { return -1; } values_byname = rbtree_create(valuename_cmp, free, 0); if (!values_byname) { return -1; } values_byvalue = rbtree_create(valuevalue_cmp, NULL, 1); if (!values_byvalue) { return -1; } value_fixup = NULL; /* just to be safe. */ if (my_dict_init(dir, fn, NULL, 0) < 0) return -1; if (value_fixup) { DICT_ATTR *a; value_fixup_t *this, *next; for (this = value_fixup; this != NULL; this = next) { next = this->next; a = dict_attrbyname(this->attrstr); if (!a) { librad_log( "dict_init: No ATTRIBUTE \"%s\" defined for VALUE \"%s\"", this->attrstr, this->dval->name); return -1; /* leak, but they should die... */ } this->dval->attr = a->attr; /* * Add the value into the dictionary. */ if (rbtree_insert(values_byname, this->dval) == 0) { librad_log("dict_addvalue: Duplicate value name %s for attribute %s", this->dval->name, a->name); return -1; } /* * Allow them to use the old name, but * prefer the new name when printing * values. */ if (!rbtree_find(values_byvalue, this->dval)) { rbtree_insert(values_byvalue, this->dval); } free(this); /* * Just so we don't lose track of things. */ value_fixup = next; } } return 0;}/* * Get an attribute by its numerical value. */DICT_ATTR *dict_attrbyvalue(int val){ /* * If it's an on-the-wire base attribute, return * the cached value for it. */ if ((val >= 0) && (val < 256)) { return base_attributes[val]; } else { DICT_ATTR myattr; myattr.attr = val; return rbtree_finddata(attributes_byvalue, &myattr); } return NULL; /* never reached, but useful */}/* * Get an attribute by its name. */DICT_ATTR *dict_attrbyname(const char *name){ DICT_ATTR myattr; strNcpy(myattr.name, name, sizeof(myattr.name)); return rbtree_finddata(attributes_byname, &myattr);}/* * Associate a value with an attribute and return it. */DICT_VALUE *dict_valbyattr(int attr, int val){ DICT_VALUE myval; myval.attr = attr; myval.value = val; return rbtree_finddata(values_byvalue, &myval);}/* * Get a value by its name. * If you pass an actual attr, it will try to match it. * If you just want it to return on the first match, * send it 0 as the attr. I hope this works the way it * seems to. :) --kph */DICT_VALUE *dict_valbyname(int attr, const char *name){ DICT_VALUE myval; myval.attr = attr; strNcpy(myval.name, name, sizeof(myval.name)); return rbtree_finddata(values_byname, &myval);}/* * Get the vendor PEC based on the vendor name */int dict_vendorbyname(const char *name){ DICT_VENDOR *v; /* * Find the vendor, if any. */ for (v = dictionary_vendors; v; v = v->next) { if (strcasecmp(name, v->name) == 0) { return v->vendorpec; } } return 0;}/* * Return the vendor struct based on the PEC. */DICT_VENDOR *dict_vendorbyvalue(int vendor){ DICT_VENDOR *v; /* * Find the vendor, if any. */ for (v = dictionary_vendors; v; v = v->next) { if (vendor == v->vendorpec) { return v; } } return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -