/* Allocate memory for a new additional variable * and link it to a configuration group. * type==0 results in creating a new group instance with the default values. * The group is created with CFG_GROUP_UNKNOWN type if it does not exist. * Note: this function is usable only before the configuration is shmized. */ int new_add_var(str *group_name, unsigned int group_id, str *var_name, void *val, unsigned int type) { cfg_group_t *group; cfg_add_var_t *add_var = NULL, **add_var_p; int len; if (type && !var_name) { LOG(L_ERR, "ERROR: new_add_var(): Missing variable specification\n"); goto error; } if (type) LOG(L_DBG, "DEBUG: new_add_var(): declaring a new variable instance %.*s[%u].%.*s\n", group_name->len, group_name->s, group_id, var_name->len, var_name->s); else LOG(L_DBG, "DEBUG: new_add_var(): declaring a new group instance %.*s[%u]\n", group_name->len, group_name->s, group_id); if (cfg_shmized) { LOG(L_ERR, "ERROR: new_add_var(): too late, the configuration has already been shmized\n"); goto error; } group = cfg_lookup_group(group_name->s, group_name->len); if (!group) { /* create a new group with NULL values, it will be filled in later */ group = cfg_new_group(group_name->s, group_name->len, 0 /* num */, NULL /* mapping */, NULL /* vars */, 0 /* size */, NULL /* handle */); if (!group) goto error; /* It is not yet known whether the group will be static or dynamic */ group->dynamic = CFG_GROUP_UNKNOWN; } add_var = (cfg_add_var_t *)pkg_malloc(sizeof(cfg_add_var_t) + (type ? (var_name->len - 1) : 0)); if (!add_var) { LOG(L_ERR, "ERROR: new_add_var(): Not enough memory\n"); goto error; } memset(add_var, 0, sizeof(cfg_add_var_t) + (type ? (var_name->len - 1) : 0)); add_var->group_id = group_id; if (type) { add_var->name_len = var_name->len; memcpy(add_var->name, var_name->s, var_name->len); switch (type) { case CFG_VAR_INT: add_var->val.i = (int)(long)val; break; case CFG_VAR_STR: len = ((str *)val)->len; if (len) { add_var->val.s.s = (char *)pkg_malloc(sizeof(char) * len); if (!add_var->val.s.s) { LOG(L_ERR, "ERROR: new_add_var(): Not enough memory\n"); goto error; } memcpy(add_var->val.s.s, ((str *)val)->s, len); } else { add_var->val.s.s = NULL; } add_var->val.s.len = len; break; case CFG_VAR_STRING: if (val) { len = strlen((char *)val); add_var->val.ch = (char *)pkg_malloc(sizeof(char) * (len + 1)); if (!add_var->val.ch) { LOG(L_ERR, "ERROR: new_add_var(): Not enough memory\n"); goto error; } memcpy(add_var->val.ch, (char *)val, len); add_var->val.ch[len] = '\0'; } else { add_var->val.ch = NULL; } break; default: LOG(L_ERR, "ERROR: new_add_var(): unsupported value type: %u\n", type); goto error; } add_var->type = type; } /* order the list by group_id, it will be easier to count the group instances */ for( add_var_p = &group->add_var; *add_var_p && ((*add_var_p)->group_id <= group_id); add_var_p = &((*add_var_p)->next)); add_var->next = *add_var_p; *add_var_p = add_var; return 0; error: if (!type) LOG(L_ERR, "ERROR: new_add_var(): failed to add the additional group instance: %.*s[%u]\n", group_name->len, group_name->s, group_id); else LOG(L_ERR, "ERROR: new_add_var(): failed to add the additional variable instance: %.*s[%u].%.*s\n", group_name->len, group_name->s, group_id, var_name->len, var_name->s); if (add_var) pkg_free(add_var); return -1; }
/* allocates memory for a new config script variable * The value of the variable is not set! */ cfg_script_var_t *new_cfg_script_var(char *gname, char *vname, unsigned int type, char *descr) { cfg_group_t *group; cfg_script_var_t *var; int gname_len, vname_len, descr_len; LOG(L_DBG, "DEBUG: new_cfg_script_var(): declaring %s.%s\n", gname, vname); if (cfg_shmized) { LOG(L_ERR, "ERROR: new_cfg_script_var(): too late variable declaration, " "the config has been already shmized\n"); return NULL; } gname_len = strlen(gname); vname_len = strlen(vname); /* the group may have been already declared */ group = cfg_lookup_group(gname, gname_len); if (group) { if (group->dynamic == CFG_GROUP_STATIC) { /* the group has been already declared by a module or by the core */ LOG(L_ERR, "ERROR: new_cfg_script_var(): " "configuration group has been already declared: %s\n", gname); return NULL; } /* the dynamic or empty group is found */ /* verify that the variable does not exist */ for ( var = (cfg_script_var_t *)group->vars; var; var = var->next ) { if ((var->name_len == vname_len) && (memcmp(var->name, vname, vname_len) == 0)) { LOG(L_ERR, "ERROR: new_cfg_script_var(): variable already exists: %s.%s\n", gname, vname); return NULL; } } if (group->dynamic == CFG_GROUP_UNKNOWN) group->dynamic = CFG_GROUP_DYNAMIC; } else { /* create a new group with NULL values, we will fix it later, when all the variables are known */ group = cfg_new_group(gname, gname_len, 0 /* num */, NULL /* mapping */, NULL /* vars */, 0 /* size */, NULL /* handle */); if (!group) goto error; group->dynamic = CFG_GROUP_DYNAMIC; } switch (type) { case CFG_VAR_INT: group->size = ROUND_INT(group->size); group->size += sizeof(int); break; case CFG_VAR_STR: group->size = ROUND_POINTER(group->size); group->size += sizeof(str); break; default: LOG(L_ERR, "ERROR: new_cfg_script_var(): unsupported variable type\n"); return NULL; } group->num++; if (group->num > CFG_MAX_VAR_NUM) { LOG(L_ERR, "ERROR: new_cfg_script_var(): too many variables (%d) within a single group," " the limit is %d. Increase CFG_MAX_VAR_NUM, or split the group into multiple" " definitions.\n", group->num, CFG_MAX_VAR_NUM); return NULL; } var = (cfg_script_var_t *)pkg_malloc(sizeof(cfg_script_var_t)); if (!var) goto error; memset(var, 0, sizeof(cfg_script_var_t)); var->type = type; /* add the variable to the group */ var->next = (cfg_script_var_t *)(void *)group->vars; group->vars = (char *)(void *)var; /* clone the name of the variable */ var->name = (char *)pkg_malloc(sizeof(char) * (vname_len + 1)); if (!var->name) goto error; memcpy(var->name, vname, vname_len + 1); var->name_len = vname_len; if (descr) { /* save the description */ descr_len = strlen(descr); var->descr = (char *)pkg_malloc(sizeof(char) * (descr_len + 1)); if (!var->descr) goto error; memcpy(var->descr, descr, descr_len + 1); } return var; error: LOG(L_ERR, "ERROR: new_cfg_script_var(): not enough memory\n"); return NULL; }