Exemplo n.º 1
0
/* 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;
}
Exemplo n.º 2
0
/* 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;
}