4 * Copyright (C) 2008 iptelorg GmbH
6 * This file is part of ser, a free SIP server.
8 * ser is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
13 * For a license to use the ser software under conditions
14 * other than those described here, or to purchase support for this
15 * software, please contact iptel.org by e-mail at the following addresses:
18 * ser is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 * 2008-01-24 dynamic groups are introduced in order to make
30 * variable declaration possible in the script (Miklos)
35 #include "../mem/mem.h"
37 #include "cfg_struct.h"
39 #include "cfg_script.h"
41 /* allocates memory for a new config script variable
42 * The value of the variable is not set!
44 cfg_script_var_t *new_cfg_script_var(char *gname, char *vname, unsigned int type,
48 cfg_script_var_t *var;
49 int gname_len, vname_len, descr_len;
51 LOG(L_DBG, "DEBUG: new_cfg_script_var(): declaring %s.%s\n", gname, vname);
54 LOG(L_ERR, "ERROR: new_cfg_script_var(): too late variable declaration, "
55 "the config has been already shmized\n");
59 gname_len = strlen(gname);
60 /* the group may have been already declared */
61 for ( group = cfg_group;
65 if ((group->name_len == gname_len) &&
66 (memcmp(group->name, gname, gname_len) == 0)) {
67 if (group->dynamic == 0) {
68 /* the group has been already declared by a module or by the core */
69 LOG(L_ERR, "ERROR: new_cfg_script_var(): "
70 "configuration group has been already declared: %s\n",
74 /* the dynamic group is found */
80 /* create a new group with NULL values, we will fix it later,
81 when all the variables are known */
82 group = cfg_new_group(gname, gname_len,
83 0 /* num */, NULL /* mapping */,
84 NULL /* vars */, 0 /* size */, NULL /* handle */);
86 if (!group) goto error;
90 /* verify that the variable does not exist */
91 vname_len = strlen(vname);
93 for ( var = (cfg_script_var_t *)group->vars;
97 if ((var->name_len == vname_len) &&
98 (memcmp(var->name, vname, vname_len) == 0)) {
99 LOG(L_ERR, "ERROR: new_cfg_script_var(): variable already exists: %s.%s\n",
107 group->size = ROUND_INT(group->size);
108 group->size += sizeof(int);
112 group->size = ROUND_POINTER(group->size);
113 group->size += sizeof(str);
117 LOG(L_ERR, "ERROR: new_cfg_script_var(): unsupported variable type\n");
122 var = (cfg_script_var_t *)pkg_malloc(sizeof(cfg_script_var_t));
123 if (!var) goto error;
124 memset(var, sizeof(cfg_script_var_t), 0);
127 /* add the variable to the group */
128 var->next = (cfg_script_var_t *)(void *)group->vars;
129 group->vars = (char *)(void *)var;
131 /* clone the name of the variable */
132 var->name = (char *)pkg_malloc(sizeof(char) * (vname_len + 1));
133 if (!var->name) goto error;
134 memcpy(var->name, vname, vname_len + 1);
135 var->name_len = vname_len;
138 /* save the description */
139 descr_len = strlen(descr);
140 var->descr = (char *)pkg_malloc(sizeof(char) * (descr_len + 1));
141 if (!var->descr) goto error;
142 memcpy(var->descr, descr, descr_len + 1);
148 LOG(L_ERR, "ERROR: new_cfg_script_var(): not enough memory\n");
152 /* fix-up the dynamically declared group:
153 * - allocate memory for the arrays
154 * - set the values within the memory block
155 * - notify the drivers about the new group
157 int cfg_script_fixup(cfg_group_t *group, unsigned char *block)
159 cfg_mapping_t *mapping = NULL;
160 cfg_def_t *def = NULL;
161 void **handle = NULL;
163 cfg_script_var_t *script_var, *script_var2;
166 mapping = (cfg_mapping_t *)pkg_malloc(sizeof(cfg_mapping_t)*group->num);
167 if (!mapping) goto error;
168 memset(mapping, 0, sizeof(cfg_mapping_t)*group->num);
170 /* The variable definition array must look like as if it was declared
171 * in C code, thus, add an additional slot at the end with NULL values */
172 def = (cfg_def_t *)pkg_malloc(sizeof(cfg_def_t)*(group->num + 1));
173 if (!def) goto error;
174 memset(def, 0, sizeof(cfg_def_t)*(group->num + 1));
176 /* fill the definition and the mapping arrays */
178 for ( i = 0, script_var = (cfg_script_var_t *)group->vars;
180 i++, script_var = script_var->next
182 /* there has been already memory allocated for the name */
183 def[i].name = script_var->name;
184 def[i].type = script_var->type | (script_var->type << CFG_INPUT_SHIFT);
185 def[i].descr = script_var->descr;
187 mapping[i].def = &(def[i]);
188 mapping[i].name_len = script_var->name_len;
190 switch (script_var->type) {
192 offset = ROUND_INT(offset);
193 mapping[i].offset = offset;
195 memcpy(block + offset, &script_var->val.i, sizeof(int));
197 offset += sizeof(int);
201 offset = ROUND_POINTER(offset);
202 mapping[i].offset = offset;
204 if (!(s.s = cfg_clone_str(script_var->val.s))) goto error;
205 s.len = script_var->val.s.len;
206 memcpy(block + offset, &s, sizeof(str));
207 mapping[i].flag |= cfg_var_shmized;
209 offset += sizeof(str);
214 /* allocate a handle even if it will not be used to
215 directly access the variable, like handle->variable
216 cfg_get_* functions access the memory block via the handle
217 to make sure that it is always safe, thus, it must be created */
218 handle = (void **)pkg_malloc(sizeof(void *));
219 if (!handle) goto error;
221 group->handle = handle;
223 group->mapping = mapping;
225 /* everything went fine, we can free the temporary list */
226 script_var = (cfg_script_var_t *)group->vars;
229 script_var2 = script_var->next;
230 if ((script_var->type == CFG_VAR_STR) && script_var->val.s.s)
231 pkg_free(script_var->val.s.s);
232 pkg_free(script_var);
233 script_var = script_var2;
239 if (mapping) pkg_free(mapping);
240 if (def) pkg_free(def);
241 if (handle) pkg_free(handle);
243 LOG(L_ERR, "ERROR: cfg_script_fixup(): not enough memory\n");
247 /* destory a dynamically allocated group definition */
248 void cfg_script_destroy(cfg_group_t *group)
251 cfg_script_var_t *script_var, *script_var2;
253 if (group->mapping && group->mapping->def) {
254 for (i=0; i<group->num; i++) {
255 if (group->mapping->def[i].name)
256 pkg_free(group->mapping->def[i].name);
257 if (group->mapping->def[i].descr)
258 pkg_free(group->mapping->def[i].descr);
260 pkg_free(group->mapping->def);
262 if (group->mapping) pkg_free(group->mapping);
263 if (group->handle) pkg_free(group->handle);
265 /* it may happen that the the temporary var list
266 still exists because the fixup failed and did not complete */
267 script_var = (cfg_script_var_t *)group->vars;
269 script_var2 = script_var->next;
270 if ((script_var->type == CFG_VAR_STR) && script_var->val.s.s)
271 pkg_free(script_var->val.s.s);
272 pkg_free(script_var);
273 script_var = script_var2;