2 * Copyright (C) 2007 iptelorg GmbH
4 * This file is part of Kamailio, a free SIP server.
6 * Kamailio is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version
11 * Kamailio is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "cfg_struct.h"
28 #include "cfg_script.h"
32 /* linked list of all the registered cfg contexts */
33 static cfg_ctx_t *cfg_ctx_list = NULL;
35 /* creates a new config context that is an interface to the
36 * cfg variables with write permission
38 int cfg_register_ctx(cfg_ctx_t **handle, cfg_on_declare on_declare_cb)
44 /* allocate memory for the new context
45 * Better to use shm mem, because 'changed' and 'lock'
46 * must be in shm mem anyway */
47 ctx = (cfg_ctx_t *)shm_malloc(sizeof(cfg_ctx_t));
52 memset(ctx, 0, sizeof(cfg_ctx_t));
53 if (lock_init(&ctx->lock) == 0) {
54 LM_ERR("failed to init lock\n");
59 /* add the new ctx to the beginning of the list */
60 ctx->next = cfg_ctx_list;
63 /* let the driver know about the already registered groups
64 * The handle of the context must be set before calling the
65 * on_declare callbacks. */
68 ctx->on_declare_cb = on_declare_cb;
70 for (group = cfg_group;
74 /* dynamic groups are not ready, the callback
75 * will be called later when the group is fixed-up */
76 if (group->dynamic != CFG_GROUP_STATIC) continue;
78 gname.s = group->name;
79 gname.len = group->name_len;
80 on_declare_cb(&gname, group->mapping->def);
87 /* free the memory allocated for the contexts */
88 void cfg_ctx_destroy(void)
90 cfg_ctx_t *ctx, *ctx2;
92 for (ctx = cfg_ctx_list;
102 /* notify the drivers about the new config definition */
103 void cfg_notify_drivers(char *group_name, int group_name_len, cfg_def_t *def)
108 gname.s = group_name;
109 gname.len = group_name_len;
111 for (ctx = cfg_ctx_list;
115 if (ctx->on_declare_cb)
116 ctx->on_declare_cb(&gname, def);
119 /* placeholder for a temporary string */
120 static char *temp_string = NULL;
122 /* convert the value to the requested type */
123 int convert_val(unsigned int val_type, void *val,
124 unsigned int var_type, void **new_val)
129 static char buf[INT2STR_MAX_LEN];
131 /* we have to convert from val_type to var_type */
132 switch (CFG_INPUT_MASK(var_type)) {
134 if (val_type == CFG_VAR_INT) {
138 } else if (val_type == CFG_VAR_STRING) {
139 if (!val || (((char *)val)[0] == '\0')) {
140 LM_ERR("cannot convert NULL string value to integer\n");
143 *new_val = (void *)(long)strtol((char *)val, &end, 10);
145 LM_ERR("cannot convert string to integer '%s'\n",
151 } else if (val_type == CFG_VAR_STR) {
152 if (!((str *)val)->len || !((str *)val)->s) {
153 LM_ERR("cannot convert NULL str value to integer\n");
156 if (str2sint((str *)val, &i)) {
157 LM_ERR("cannot convert string to integer '%.*s'\n",
158 ((str *)val)->len, ((str *)val)->s);
161 *new_val = (void *)(long)i;
166 case CFG_INPUT_STRING:
167 if (val_type == CFG_VAR_INT) {
168 buf[snprintf(buf, sizeof(buf)-1, "%ld", (long)val)] = '\0';
172 } else if (val_type == CFG_VAR_STRING) {
176 } else if (val_type == CFG_VAR_STR) {
177 if (!((str *)val)->s) {
181 /* the value may not be zero-terminated, thus,
182 * a new variable has to be allocated with larger memory space */
183 if (temp_string) pkg_free(temp_string);
184 temp_string = (char *)pkg_malloc(sizeof(char) * (((str *)val)->len + 1));
189 memcpy(temp_string, ((str *)val)->s, ((str *)val)->len);
190 temp_string[((str *)val)->len] = '\0';
191 *new_val = (void *)temp_string;
198 if (val_type == CFG_VAR_INT) {
199 s.len = snprintf(buf, sizeof(buf)-1, "%ld", (long)val);
202 *new_val = (void *)&s;
205 } else if (val_type == CFG_VAR_STRING) {
207 s.len = (s.s) ? strlen(s.s) : 0;
208 *new_val = (void *)&s;
211 } else if (val_type == CFG_VAR_STR) {
221 LM_ERR("got a value with type %u, but expected %u\n",
222 val_type, CFG_INPUT_MASK(var_type));
226 void convert_val_cleanup(void)
229 pkg_free(temp_string);
234 /* returns the size of the variable */
235 static int cfg_var_size(cfg_mapping_t *var)
237 switch (CFG_VAR_TYPE(var)) {
243 return sizeof(char *);
248 case CFG_VAR_POINTER:
249 return sizeof(void *);
252 LM_CRIT("unknown type: %u\n", CFG_VAR_TYPE(var));
257 /* Update the varibales of the array within the meta structure
258 * with the new default value.
259 * The array is cloned before a change if clone is set to 1.
261 static int cfg_update_defaults(cfg_group_meta_t *meta,
262 cfg_group_t *group, cfg_mapping_t *var, char *new_val,
266 cfg_group_inst_t *array, *ginst;
268 if (!(array = meta->array))
270 for (i = 0; i < meta->num; i++) {
271 ginst = (cfg_group_inst_t *)((char *)array
272 + (sizeof(cfg_group_inst_t) + group->size - 1) * i);
274 if (!CFG_VAR_TEST(ginst, var)) {
275 /* The variable uses the default value, it needs to be rewritten. */
276 if (clone && !clone_done) {
277 /* The array needs to be cloned before the modification */
278 if (!(array = cfg_clone_array(meta, group)))
280 ginst = (cfg_group_inst_t *)translate_pointer((char *)array,
283 /* re-link the array to the meta-data */
287 if(ginst->vars + var->offset) {
288 memcpy(ginst->vars + var->offset, new_val, cfg_var_size(var));
290 LM_ERR("invalid variable offset\n");
297 /* sets the value of a variable without the need of commit
302 * 1: variable has not been found
304 int cfg_set_now(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
305 void *val, unsigned int val_type)
311 cfg_block_t *block = NULL;
313 char *old_string = NULL;
314 void **replaced = NULL;
315 cfg_child_cb_t *child_cb = NULL;
316 cfg_group_inst_t *group_inst = NULL, *new_array = NULL;
317 unsigned char *var_block;
319 /* verify the context even if we do not need it now
320 * to make sure that a cfg driver has called the function
321 * (very very weak security) */
323 LM_ERR("context is undefined\n");
327 if ((val_type == CFG_VAR_UNSET) && !group_id) {
328 LM_ERR("Only group instance values can be deleted\n");
332 if (group_id && !cfg_shmized) {
333 /* The config group has not been shmized yet, but
334 * an additional instance of a variable needs to be added to the group.
335 * Add this instance to the linked list of variables, they
336 * will be fixed later. */
337 return new_add_var(group_name, *group_id, var_name,
341 /* look-up the group and the variable */
342 if (cfg_lookup_var(group_name, var_name, &group, &var)) {
344 /* The group may be dynamic which is not yet ready
346 if ((group = cfg_lookup_group(group_name->s, group_name->len))
347 && (group->dynamic == CFG_GROUP_DYNAMIC))
348 return cfg_set_script_var(group, var_name, val, val_type);
353 /* check whether the variable is read-only */
354 if (var->def->type & CFG_READONLY) {
355 LM_ERR("variable is read-only\n");
359 /* The additional variable instances having per-child process callback
360 * with CFG_CB_ONLY_ONCE flag cannot be rewritten.
361 * The reason is that such variables typically set global parameters
362 * as opposed to per-process variables. Hence, it is not possible to set
363 * the group handle temporary to another block, and then reset it back later. */
365 && var->def->on_set_child_cb
366 && var->def->type & CFG_CB_ONLY_ONCE ) {
367 LM_ERR("This variable does not support muliple values.\n");
371 /* check whether we have to convert the type */
372 if ((val_type != CFG_VAR_UNSET)
373 && convert_val(val_type, val, CFG_INPUT_TYPE(var), &v))
376 if ((val_type != CFG_VAR_UNSET)
377 && (CFG_INPUT_TYPE(var) == CFG_INPUT_INT)
378 && (var->def->min || var->def->max)) {
379 /* perform a simple min-max check for integers */
380 if (((int)(long)v < var->def->min)
381 || ((int)(long)v > var->def->max)) {
382 LM_ERR("integer value is out of range\n");
387 if ((val_type != CFG_VAR_UNSET)
388 && var->def->on_change_cb) {
389 /* Call the fixup function.
390 * There is no need to set a temporary cfg handle,
391 * becaue a single variable is changed */
393 var_block = *(group->handle);
396 LM_ERR("Local configuration is missing\n");
399 group_inst = cfg_find_group(CFG_GROUP_META(cfg_local, group),
403 LM_ERR("local group instance %.*s[%u] is not found\n",
404 group_name->len, group_name->s, *group_id);
407 var_block = group_inst->vars;
410 if (var->def->on_change_cb(var_block,
414 LM_ERR("fixup failed\n");
420 /* Set the per-child process callback only if the default value is changed.
421 * The callback of other instances will be called when the config is
422 * switched to that instance. */
423 if (!group_id && var->def->on_set_child_cb) {
424 /* get the name of the variable from the internal struct,
425 * because var_name may be freed before the callback needs it */
427 s.len = group->name_len;
428 s2.s = var->def->name;
429 s2.len = var->name_len;
430 child_cb = cfg_child_cb_new(&s, &s2,
431 var->def->on_set_child_cb,
440 /* make sure that nobody else replaces the global config
441 * while the new one is prepared */
445 group_inst = cfg_find_group(CFG_GROUP_META(*cfg_global, group),
449 LM_ERR("global group instance %.*s[%u] is not found\n",
450 group_name->len, group_name->s, *group_id);
453 if ((val_type == CFG_VAR_UNSET) && !CFG_VAR_TEST(group_inst, var)) {
454 /* nothing to do, the variable is not set in the group instance */
456 LM_DBG("The variable is not set\n");
459 var_block = group_inst->vars;
462 var_block = CFG_GROUP_DATA(*cfg_global, group);
465 if (var->def->type & CFG_ATOMIC) {
466 /* atomic change is allowed, we can rewrite the value
467 * directly in the global config */
468 p = var_block + var->offset;
471 /* clone the memory block, and prepare the modification */
472 if (!(block = cfg_clone_global())) goto error;
475 /* The additional array of the group needs to be also cloned.
476 * When any of the variables within this array is changed, then
477 * the complete config block and this array is replaced. */
478 if (!(new_array = cfg_clone_array(CFG_GROUP_META(*cfg_global, group), group)))
480 group_inst = (cfg_group_inst_t *)translate_pointer((char *)new_array,
481 (char *)CFG_GROUP_META(*cfg_global, group)->array,
483 var_block = group_inst->vars;
484 CFG_GROUP_META(block, group)->array = new_array;
486 /* The additional array may need to be replaced depending
487 * on whether or not there is any variable in the array set
488 * to the default value which is changed now. If this is the case,
489 * then the array will be replaced later when the variables are
492 var_block = CFG_GROUP_DATA(block, group);
494 p = var_block + var->offset;
497 /* we are allowed to rewrite the value on-the-fly
498 * The handle either points to group->vars, or to the
499 * shared memory block (dynamic group) */
500 p = *(group->handle) + var->offset;
503 if (val_type != CFG_VAR_UNSET) {
504 /* set the new value */
505 switch (CFG_VAR_TYPE(var)) {
507 *(int *)p = (int)(long)v;
511 /* clone the string to shm mem */
513 s.len = (s.s) ? strlen(s.s) : 0;
514 if (cfg_clone_str(&s, &s)) goto error;
515 old_string = *(char **)p;
520 /* clone the string to shm mem */
522 if (cfg_clone_str(&s, &s)) goto error;
523 old_string = *(char **)p;
524 memcpy(p, &s, sizeof(str));
527 case CFG_VAR_POINTER:
532 if (group_inst && !CFG_VAR_TEST_AND_SET(group_inst, var))
533 old_string = NULL; /* the string is the same as the default one,
534 * it cannot be freed */
536 /* copy the default value to the group instance */
537 if ((CFG_VAR_TYPE(var) == CFG_VAR_STRING)
538 || (CFG_VAR_TYPE(var) == CFG_VAR_STR))
539 old_string = *(char **)p;
540 memcpy(p, CFG_GROUP_DATA(*cfg_global, group) + var->offset, cfg_var_size(var));
542 CFG_VAR_TEST_AND_RESET(group_inst, var);
547 /* the default value is changed, the copies of this value
548 * need to be also updated */
549 if (cfg_update_defaults(CFG_GROUP_META(block ? block : *cfg_global, group),
551 block ? 1 : 0) /* clone if needed */
554 if (block && (CFG_GROUP_META(block, group)->array != CFG_GROUP_META(*cfg_global, group)->array))
555 new_array = CFG_GROUP_META(block, group)->array;
558 if (old_string || new_array) {
559 /* prepare the array of the replaced strings,
560 * and replaced group instances,
561 * they will be freed when the old block is freed */
562 replaced = (void **)shm_malloc(sizeof(void *)
563 * ((old_string?1:0) + (new_array?1:0) + 1));
570 replaced[i] = old_string;
574 replaced[i] = CFG_GROUP_META(*cfg_global, group)->array;
579 /* replace the global config with the new one */
580 if (block) cfg_install_global(block, replaced, child_cb, child_cb);
583 /* cfg_set() may be called more than once before forking */
584 if (old_string && (var->flag & cfg_var_shmized))
585 shm_free(old_string);
587 /* flag the variable because there is no need
588 * to shmize it again */
589 var->flag |= cfg_var_shmized;
591 /* the global config does not have to be replaced,
592 * but the child callback has to be installed, otherwise the
593 * child processes will miss the change */
595 cfg_install_child_cb(child_cb, child_cb);
598 if (val_type == CFG_VAR_INT)
599 LM_INFO("%.*s.%.*s has been changed to %d\n",
600 group_name->len, group_name->s,
601 var_name->len, var_name->s,
604 else if (val_type == CFG_VAR_STRING)
605 LM_INFO("%.*s.%.*s has been changed to \"%s\"\n",
606 group_name->len, group_name->s,
607 var_name->len, var_name->s,
610 else if (val_type == CFG_VAR_STR)
611 LM_INFO("%.*s.%.*s has been changed to \"%.*s\"\n",
612 group_name->len, group_name->s,
613 var_name->len, var_name->s,
614 ((str *)val)->len, ((str *)val)->s);
616 else if (val_type == CFG_VAR_UNSET)
617 LM_INFO("%.*s.%.*s has been deleted\n",
618 group_name->len, group_name->s,
619 var_name->len, var_name->s);
622 LM_INFO("%.*s.%.*s has been changed\n",
623 group_name->len, group_name->s,
624 var_name->len, var_name->s);
627 LM_INFO("group id = %u\n", *group_id);
629 convert_val_cleanup();
633 if (cfg_shmized) CFG_WRITER_UNLOCK();
634 if (block) cfg_block_free(block);
635 if (new_array) shm_free(new_array);
636 if (child_cb) cfg_child_cb_free_list(child_cb);
637 if (replaced) shm_free(replaced);
640 LM_ERR("failed to set the variable: %.*s.%.*s\n",
641 group_name->len, group_name->s,
642 var_name->len, var_name->s);
645 convert_val_cleanup();
649 /* wrapper function for cfg_set_now */
650 int cfg_set_now_int(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id,
651 str *var_name, int val)
653 return cfg_set_now(ctx, group_name, group_id, var_name,
654 (void *)(long)val, CFG_VAR_INT);
657 /* wrapper function for cfg_set_now */
658 int cfg_set_now_string(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id,
659 str *var_name, char *val)
661 return cfg_set_now(ctx, group_name, group_id, var_name,
662 (void *)val, CFG_VAR_STRING);
665 /* wrapper function for cfg_set_now */
666 int cfg_set_now_str(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id,
667 str *var_name, str *val)
669 return cfg_set_now(ctx, group_name, group_id, var_name,
670 (void *)val, CFG_VAR_STR);
673 /* Delete a variable from the group instance.
674 * wrapper function for cfg_set_now */
675 int cfg_del_now(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id,
678 return cfg_set_now(ctx, group_name, group_id, var_name,
679 NULL, CFG_VAR_UNSET);
682 /* sets the value of a variable but does not commit the change
687 * 1: variable has not been found
689 int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id,
690 str *var_name, void *val, unsigned int val_type)
695 unsigned char *temp_handle;
696 int temp_handle_created;
697 cfg_changed_var_t *changed = NULL, **changed_p;
700 cfg_group_inst_t *group_inst = NULL;
701 unsigned char *var_block;
704 /* the cfg has not been shmized yet, there is no
705 * point in registering the change and committing it later */
706 return cfg_set_now(ctx, group_name, group_id, var_name,
710 LM_ERR("context is undefined\n");
714 if ((val_type == CFG_VAR_UNSET) && !group_id) {
715 LM_ERR("Only group instance values can be deleted\n");
719 /* look-up the group and the variable */
720 if (cfg_lookup_var(group_name, var_name, &group, &var))
723 /* check whether the variable is read-only */
724 if (var->def->type & CFG_READONLY) {
725 LM_ERR("variable is read-only\n");
729 /* The additional variable instances having per-child process callback
730 * with CFG_CB_ONLY_ONCE flag cannot be rewritten.
731 * The reason is that such variables typically set global parameters
732 * as opposed to per-process variables. Hence, it is not possible to set
733 * the group handle temporary to another block, and then reset it back later. */
735 && var->def->on_set_child_cb
736 && var->def->type & CFG_CB_ONLY_ONCE) {
737 LM_ERR("This variable does not support muliple values.\n");
741 /* check whether we have to convert the type */
742 if ((val_type != CFG_VAR_UNSET)
743 && convert_val(val_type, val, CFG_INPUT_TYPE(var), &v))
746 if ((val_type != CFG_VAR_UNSET)
747 && (CFG_INPUT_TYPE(var) == CFG_INPUT_INT)
748 && (var->def->min || var->def->max)) {
749 /* perform a simple min-max check for integers */
750 if (((int)(long)v < var->def->min)
751 || ((int)(long)v > var->def->max)) {
752 LM_ERR("integer value is out of range\n");
757 /* the ctx must be locked while reading and writing
758 * the list of changed variables */
761 if ((val_type != CFG_VAR_UNSET) && var->def->on_change_cb) {
762 /* The fixup function must see also the
763 * not yet committed values, so a temporary handle
764 * must be prepared that points to the new config.
765 * Only the values within the group are applied,
766 * other modifications are not visible to the callback.
767 * The local config is the base. */
769 var_block = *(group->handle);
772 LM_ERR("Local configuration is missing\n");
775 group_inst = cfg_find_group(CFG_GROUP_META(cfg_local, group),
779 LM_ERR("local group instance %.*s[%u] is not found\n",
780 group_name->len, group_name->s, *group_id);
783 var_block = group_inst->vars;
786 if (ctx->changed_first) {
787 temp_handle = (unsigned char *)pkg_malloc(group->size);
792 temp_handle_created = 1;
793 memcpy(temp_handle, var_block, group->size);
795 /* apply the changes */
796 for ( changed = ctx->changed_first;
798 changed = changed->next
800 if (changed->group != group)
802 if ((!group_id && !changed->group_id_set) /* default values */
803 || (group_id && !changed->group_id_set
804 && !CFG_VAR_TEST(group_inst, changed->var))
805 /* default value is changed which affects the group_instance */
806 || (group_id && changed->group_id_set
807 && (*group_id == changed->group_id))
808 /* change within the group instance */
810 memcpy( temp_handle + changed->var->offset,
811 changed->new_val.vraw,
812 cfg_var_size(changed->var));
815 /* there is not any change */
816 temp_handle = var_block;
817 temp_handle_created = 0;
820 if (var->def->on_change_cb(temp_handle,
824 LM_ERR("fixup failed\n");
825 if (temp_handle_created) pkg_free(temp_handle);
828 if (temp_handle_created) pkg_free(temp_handle);
832 /* everything went ok, we can add the new value to the list */
833 size = sizeof(cfg_changed_var_t)
834 - sizeof(((cfg_changed_var_t*)0)->new_val)
835 + ((val_type != CFG_VAR_UNSET) ? cfg_var_size(var) : 0);
836 changed = (cfg_changed_var_t *)shm_malloc(size);
841 memset(changed, 0, size);
842 changed->group = group;
845 changed->group_id = *group_id;
846 changed->group_id_set = 1;
849 if (val_type != CFG_VAR_UNSET) {
850 switch (CFG_VAR_TYPE(var)) {
853 changed->new_val.vint = (int)(long)v;
857 /* clone the string to shm mem */
859 s.len = (s.s) ? strlen(s.s) : 0;
860 if (cfg_clone_str(&s, &s)) goto error;
861 changed->new_val.vp = s.s;
865 /* clone the string to shm mem */
867 if (cfg_clone_str(&s, &s)) goto error;
868 changed->new_val.vstr=s;
871 case CFG_VAR_POINTER:
872 changed->new_val.vp=v;
877 changed->del_value = 1;
880 /* Order the changes by group + group_id + original order.
881 * Hence, the list is still kept in order within the group.
882 * The changes can be committed faster this way, the group instances
883 * do not have to be looked-up for each and every variable. */
884 /* Check whether there is any variable in the list which
885 * belongs to the same group */
886 for ( changed_p = &ctx->changed_first;
887 *changed_p && ((*changed_p)->group != changed->group);
888 changed_p = &(*changed_p)->next);
889 /* try to find the group instance, and move changed_p to the end of
893 && ((*changed_p)->group == changed->group)
894 && (!(*changed_p)->group_id_set
895 || ((*changed_p)->group_id_set && changed->group_id_set
896 && ((*changed_p)->group_id <= changed->group_id)));
897 changed_p = &(*changed_p)->next);
898 /* Add the new variable before *changed_p */
899 changed->next = *changed_p;
900 *changed_p = changed;
904 if (val_type == CFG_VAR_INT)
905 LM_INFO("%.*s.%.*s is going to be changed to %d "
907 group_name->len, group_name->s,
908 var_name->len, var_name->s,
912 else if (val_type == CFG_VAR_STRING)
913 LM_INFO("%.*s.%.*s is going to be changed to \"%s\" "
915 group_name->len, group_name->s,
916 var_name->len, var_name->s,
920 else if (val_type == CFG_VAR_STR)
921 LM_INFO("%.*s.%.*s is going to be changed to \"%.*s\" "
923 group_name->len, group_name->s,
924 var_name->len, var_name->s,
925 ((str *)val)->len, ((str *)val)->s,
928 else if (val_type == CFG_VAR_UNSET)
929 LM_INFO("%.*s.%.*s is going to be deleted "
931 group_name->len, group_name->s,
932 var_name->len, var_name->s,
936 LM_INFO("%.*s.%.*s is going to be changed "
938 group_name->len, group_name->s,
939 var_name->len, var_name->s,
943 LM_INFO("group id = %u [context=%p]\n",
947 convert_val_cleanup();
952 if (changed) shm_free(changed);
954 LM_ERR("failed to set the variable: %.*s.%.*s\n",
955 group_name->len, group_name->s,
956 var_name->len, var_name->s);
958 convert_val_cleanup();
962 /* wrapper function for cfg_set_delayed */
963 int cfg_set_delayed_int(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id,
964 str *var_name, int val)
966 return cfg_set_delayed(ctx, group_name, group_id, var_name,
967 (void *)(long)val, CFG_VAR_INT);
970 /* wrapper function for cfg_set_delayed */
971 int cfg_set_delayed_string(cfg_ctx_t *ctx, str *group_name,
972 unsigned int *group_id, str *var_name, char *val)
974 return cfg_set_delayed(ctx, group_name, group_id, var_name,
975 (void *)val, CFG_VAR_STRING);
978 /* wrapper function for cfg_set_delayed */
979 int cfg_set_delayed_str(cfg_ctx_t *ctx, str *group_name,
980 unsigned int *group_id, str *var_name, str *val)
982 return cfg_set_delayed(ctx, group_name, group_id, var_name,
983 (void *)val, CFG_VAR_STR);
986 /* Delete a variable from the group instance.
987 * wrapper function for cfg_set_delayed */
988 int cfg_del_delayed(cfg_ctx_t *ctx, str *group_name,
989 unsigned int *group_id, str *var_name)
991 return cfg_set_delayed(ctx, group_name, group_id, var_name,
992 NULL, CFG_VAR_UNSET);
995 /* commits the previously prepared changes within the context */
996 int cfg_commit(cfg_ctx_t *ctx)
998 int replaced_num = 0;
999 cfg_changed_var_t *changed, *changed2;
1000 cfg_block_t *block = NULL;
1001 void **replaced = NULL;
1002 cfg_child_cb_t *child_cb;
1003 cfg_child_cb_t *child_cb_first = NULL;
1004 cfg_child_cb_t *child_cb_last = NULL;
1009 cfg_group_inst_t *group_inst = NULL;
1012 LM_ERR("context is undefined\n");
1016 if (!cfg_shmized) return 0; /* nothing to do */
1018 /* the ctx must be locked while reading and writing
1019 * the list of changed variables */
1022 /* is there any change? */
1023 if (!ctx->changed_first) goto done;
1025 /* Count the number of replaced strings,
1026 * and replaced group arrays.
1027 * Prepare the linked list of per-child process
1028 * callbacks, that will be added to the global list. */
1029 for(changed = ctx->changed_first, group = NULL; changed;
1030 changed = changed->next) {
1031 /* Each string/str potentially causes an old string to be freed
1032 * unless the variable of an additional group instance is set
1033 * which uses the default value. This case cannot be determined
1034 * without locking *cfg_global, hence, it is better to count these
1035 * strings as well even though the slot might not be used later. */
1036 if((CFG_VAR_TYPE(changed->var) == CFG_VAR_STRING)
1037 || (CFG_VAR_TYPE(changed->var) == CFG_VAR_STR))
1040 /* See the above comments for strings */
1041 if (group != changed->group) {
1043 group = changed->group;
1046 if (changed->group && !changed->group_id_set
1047 && changed->var->def->on_set_child_cb) {
1048 s.s = changed->group->name;
1049 s.len = changed->group->name_len;
1050 s2.s = changed->var->def->name;
1051 s2.len = changed->var->name_len;
1052 child_cb = cfg_child_cb_new(&s, &s2,
1053 changed->var->def->on_set_child_cb,
1054 changed->var->def->type);
1055 if (!child_cb) goto error0;
1058 child_cb_last->next = child_cb;
1060 child_cb_first = child_cb;
1061 child_cb_last = child_cb;
1066 /* allocate memory for the replaced string array */
1067 size = sizeof(void *)*(replaced_num + 1);
1068 replaced = (void **)shm_malloc(size);
1073 memset(replaced, 0 , size);
1075 /* no replacement */
1076 LM_INFO("commit operation executed without having changes\n");
1080 /* make sure that nobody else replaces the global config
1081 * while the new one is prepared */
1084 /* clone the memory block, and prepare the modification */
1085 if (!(block = cfg_clone_global()))
1088 /* Apply the modifications to the buffer.
1089 * Note that the cycle relies on the order of the groups and group
1090 * instances, i.e. the order is group + group_id + order of commits. */
1092 for(changed = ctx->changed_first, group = NULL; /* group points to the
1093 * last group array that
1094 * has been cloned */
1095 changed; changed = changed->next) {
1096 if (!changed->group_id_set) {
1097 p = CFG_GROUP_DATA(block, changed->group)
1098 + changed->var->offset;
1099 group_inst = NULL; /* force the look-up of the next group_inst */
1101 if (group != changed->group) {
1102 /* The group array has not been cloned yet. */
1103 group = changed->group;
1104 if (!(CFG_GROUP_META(block, group)->array =
1105 cfg_clone_array(CFG_GROUP_META(*cfg_global, group), group))
1107 LM_ERR("group array cannot be cloned for %.*s[%u]\n",
1108 group->name_len, group->name, changed->group_id);
1112 replaced[replaced_num] = CFG_GROUP_META(*cfg_global, group)->array;
1115 group_inst = NULL; /* fore the look-up of group_inst */
1117 if (group && (!group_inst || (group_inst->id != changed->group_id))) {
1118 group_inst = cfg_find_group(CFG_GROUP_META(block, group),
1122 if (group && !group_inst) {
1123 LM_ERR("global group instance %.*s[%u] is not found\n",
1124 group->name_len, group->name, changed->group_id);
1127 p = group_inst->vars + changed->var->offset;
1130 LM_ERR("failed to resolve valid variable offset\n");
1134 if (((changed->group_id_set && !changed->del_value
1135 && CFG_VAR_TEST_AND_SET(group_inst, changed->var))
1136 || (changed->group_id_set && changed->del_value
1137 && CFG_VAR_TEST_AND_RESET(group_inst, changed->var))
1138 || !changed->group_id_set)
1139 && ((CFG_VAR_TYPE(changed->var) == CFG_VAR_STRING)
1140 || (CFG_VAR_TYPE(changed->var) == CFG_VAR_STR))
1142 replaced[replaced_num] = *(char **)p;
1143 if (replaced[replaced_num])
1145 /* else do not increase replaced_num, because
1146 * the cfg_block_free() will stop at the first
1150 if (!changed->del_value)
1152 changed->new_val.vraw,
1153 cfg_var_size(changed->var));
1156 CFG_GROUP_DATA(block, changed->group) + changed->var->offset,
1157 cfg_var_size(changed->var));
1160 if (!changed->group_id_set) {
1161 /* the default value is changed, the copies of this value
1162 * need to be also updated */
1163 if (cfg_update_defaults(CFG_GROUP_META(block, changed->group),
1164 changed->group, changed->var, p,
1165 (group != changed->group)) /* clone if the array
1166 * has not been cloned yet */
1169 if ((group != changed->group)
1170 && (CFG_GROUP_META(block, changed->group)->array
1171 != CFG_GROUP_META(*cfg_global, changed->group)->array)
1173 /* The array has been cloned */
1174 group = changed->group;
1176 replaced[replaced_num] = CFG_GROUP_META(*cfg_global, group)->array;
1182 /* replace the global config with the new one */
1183 cfg_install_global(block, replaced, child_cb_first, child_cb_last);
1184 CFG_WRITER_UNLOCK();
1186 /* free the changed list */
1187 for ( changed = ctx->changed_first;
1191 changed2 = changed->next;
1194 ctx->changed_first = NULL;
1197 LM_INFO("config changes have been applied [context=%p]\n",
1200 CFG_CTX_UNLOCK(ctx);
1205 /* clean the new block from the cloned arrays */
1206 for (group = cfg_group;
1210 if (CFG_GROUP_META(block, group)->array
1211 && (CFG_GROUP_META(block, group)->array
1212 != CFG_GROUP_META(*cfg_global, group)->array)
1214 shm_free(CFG_GROUP_META(block, group)->array);
1215 /* the block can be freed outside of the writer lock */
1217 CFG_WRITER_UNLOCK();
1222 CFG_CTX_UNLOCK(ctx);
1224 if (child_cb_first) cfg_child_cb_free_list(child_cb_first);
1225 if (replaced) shm_free(replaced);
1230 /* drops the not yet committed changes within the context */
1231 int cfg_rollback(cfg_ctx_t *ctx)
1233 cfg_changed_var_t *changed, *changed2;
1236 LM_ERR("context is undefined\n");
1240 if (!cfg_shmized) return 0; /* nothing to do */
1242 LM_INFO("deleting the config changes [context=%p]\n",
1245 /* the ctx must be locked while reading and writing
1246 * the list of changed variables */
1249 for (changed = ctx->changed_first;
1253 changed2 = changed->next;
1255 if (!changed->del_value
1256 && ((CFG_VAR_TYPE(changed->var) == CFG_VAR_STRING)
1257 || (CFG_VAR_TYPE(changed->var) == CFG_VAR_STR))
1259 if (changed->new_val.vp)
1260 shm_free(changed->new_val.vp);
1264 ctx->changed_first = NULL;
1266 CFG_CTX_UNLOCK(ctx);
1271 /* retrieves the value of a variable
1275 * 1 - variable exists, but it is not readable
1277 int cfg_get_by_name(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id,
1278 str *var_name, void **val, unsigned int *val_type)
1283 static str s; /* we need the value even
1284 * after the function returns */
1285 cfg_group_inst_t *group_inst;
1287 /* verify the context even if we do not need it now
1288 * to make sure that a cfg driver has called the function
1289 * (very very weak security) */
1291 LM_ERR("context is undefined\n");
1295 /* look-up the group and the variable */
1296 if (cfg_lookup_var(group_name, var_name, &group, &var))
1299 if (var->def->on_change_cb) {
1300 /* The variable cannot be retrieved, because the fixup
1301 * function may have changed it, and it is better to return
1302 * an error than an incorrect value */
1308 LM_ERR("Local configuration is missing\n");
1311 group_inst = cfg_find_group(CFG_GROUP_META(cfg_local, group),
1315 LM_ERR("local group instance %.*s[%u] is not found\n",
1316 group_name->len, group_name->s, *group_id);
1319 p = group_inst->vars + var->offset;
1322 /* use the module's handle to access the variable
1323 * It means that the variable is read from the local config
1325 p = *(group->handle) + var->offset;
1328 switch (CFG_VAR_TYPE(var)) {
1330 *val = (void *)(long)*(int *)p;
1333 case CFG_VAR_STRING:
1334 *val = (void *)*(char **)p;
1338 memcpy(&s, p, sizeof(str));
1342 case CFG_VAR_POINTER:
1347 *val_type = CFG_VAR_TYPE(var);
1352 /* retrieves the default value of a variable
1356 * 1 - variable exists, but it is not readable
1358 int cfg_get_default_value_by_name(cfg_ctx_t *ctx, str *group_name,
1359 unsigned int *group_id, str *var_name, void **val,
1360 unsigned int *val_type)
1365 static str s; /* we need the value even
1366 * after the function returns */
1368 /* verify the context even if we do not need it now
1369 * to make sure that a cfg driver has called the function
1370 * (very very weak security) */
1372 LM_ERR("context is undefined\n");
1376 /* look-up the group and the variable */
1377 if (cfg_lookup_var(group_name, var_name, &group, &var)) {
1380 /* if variables exist then prevents resetting the read-only ones */
1381 if(var->def->type & CFG_READONLY)
1385 if (var->def->on_change_cb) {
1386 /* The variable cannot be retrieved, because the fixup
1387 * function may have changed it, and it is better to return
1388 * an error than an incorrect value */
1392 /* use the module's orig_handle to access the default registered value of
1393 * the variable for any group*/
1394 p = (group->orig_handle) + var->offset;
1396 switch (CFG_VAR_TYPE(var)) {
1398 *val = (void *)(long)*(int *)p;
1401 case CFG_VAR_STRING:
1402 *val = (void *)*(char **)p;
1406 memcpy(&s, p, sizeof(str));
1410 case CFG_VAR_POINTER:
1415 *val_type = CFG_VAR_TYPE(var);
1421 /* returns the description of a variable */
1422 int cfg_help(cfg_ctx_t *ctx, str *group_name, str *var_name,
1423 char **ch, unsigned int *input_type)
1427 /* verify the context even if we do not need it now
1428 * to make sure that a cfg driver has called the function
1429 * (very very weak security) */
1431 LM_ERR("context is undefined\n");
1435 /* look-up the group and the variable */
1436 if (cfg_lookup_var(group_name, var_name, NULL, &var))
1439 *ch = var->def->descr;
1441 *input_type = CFG_INPUT_TYPE(var);
1445 /* return the group name and the cfg structure definition,
1446 * and moves the handle to the next group
1451 int cfg_get_group_next(void **h,
1452 str *gname, cfg_def_t **def)
1456 group = (cfg_group_t *)(*h);
1457 if (group == NULL) return 0;
1459 gname->s = group->name;
1460 gname->len = group->name_len;
1461 (*def) = group->mapping->def;
1463 (*h) = (void *)group->next;
1467 /* Initialize the handle for cfg_diff_next() */
1468 int cfg_diff_init(cfg_ctx_t *ctx,
1472 LM_ERR("context is undefined\n");
1477 (*h) = (void *)ctx->changed_first;
1482 /* return the pending changes that have not been
1485 * 1: valid value is found
1486 * 0: no more changed value found
1487 * -1: error occurred
1489 int cfg_diff_next(void **h,
1490 str *gname, unsigned int **gid, str *vname,
1491 void **old_val, void **new_val,
1492 unsigned int *val_type)
1494 cfg_changed_var_t *changed;
1495 cfg_group_inst_t *group_inst;
1496 union cfg_var_value *pval_old, *pval_new;
1497 static str old_s, new_s; /* we need the value even
1498 * after the function returns */
1500 changed = (cfg_changed_var_t *)(*h);
1501 if (changed == NULL) return 0;
1503 gname->s = changed->group->name;
1504 gname->len = changed->group->name_len;
1505 *gid = (changed->group_id_set ? &changed->group_id : NULL);
1506 vname->s = changed->var->def->name;
1507 vname->len = changed->var->name_len;
1509 /* use the module's handle to access the variable
1510 * It means that the variable is read from the local config
1512 if (!changed->group_id_set) {
1513 pval_old = (union cfg_var_value*)
1514 (*(changed->group->handle) + changed->var->offset);
1517 LM_ERR("Local configuration is missing\n");
1520 group_inst = cfg_find_group(CFG_GROUP_META(cfg_local, changed->group),
1521 changed->group->size,
1524 LM_ERR("local group instance %.*s[%u] is not found\n",
1525 changed->group->name_len, changed->group->name,
1529 pval_old = (union cfg_var_value*)
1530 (group_inst->vars + changed->var->offset);
1532 if (!changed->del_value)
1533 pval_new = &changed->new_val;
1535 pval_new = (union cfg_var_value*)
1536 (*(changed->group->handle) + changed->var->offset);
1538 switch (CFG_VAR_TYPE(changed->var)) {
1540 *old_val = (void *)(long)pval_old->vint;
1541 *new_val = (void *)(long)pval_new->vint;
1544 case CFG_VAR_STRING:
1545 *old_val = pval_old->vp;
1546 *new_val = pval_new->vp;
1550 old_s=pval_old->vstr;
1551 *old_val = (void *)&old_s;
1552 new_s=pval_new->vstr;
1553 *new_val = (void *)&new_s;
1556 case CFG_VAR_POINTER:
1557 *old_val = pval_old->vp;
1558 *new_val = pval_new->vp;
1562 *val_type = CFG_VAR_TYPE(changed->var);
1564 (*h) = (void *)changed->next;
1568 /* release the handle of cfg_diff_next() */
1569 void cfg_diff_release(cfg_ctx_t *ctx)
1572 LM_ERR("context is undefined\n");
1576 CFG_CTX_UNLOCK(ctx);
1579 /* Add a new instance to an existing group */
1580 int cfg_add_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id)
1583 cfg_block_t *block = NULL;
1584 void **replaced = NULL;
1585 cfg_group_inst_t *new_array = NULL, *new_inst;
1587 /* verify the context even if we do not need it now
1588 * to make sure that a cfg driver has called the function
1589 * (very very weak security) */
1591 LM_ERR("context is undefined\n");
1596 /* Add a new variable without any value to
1597 * the linked list of additional values. This variable
1598 * will force a new group instance to be created. */
1599 return new_add_var(group_name, group_id, NULL /* var_name */,
1600 NULL /* val */, 0 /* type */);
1603 if (!(group = cfg_lookup_group(group_name->s, group_name->len))) {
1604 LM_ERR("group not found\n");
1608 /* make sure that nobody else replaces the global config
1609 * while the new one is prepared */
1611 if (cfg_find_group(CFG_GROUP_META(*cfg_global, group),
1615 LM_DBG("the group instance already exists\n");
1616 CFG_WRITER_UNLOCK();
1617 return 0; /* not an error */
1620 /* clone the global memory block because the additional array can be
1621 * replaced only together with the block. */
1622 if (!(block = cfg_clone_global()))
1625 /* Extend the array with a new group instance */
1626 if (!(new_array = cfg_extend_array(CFG_GROUP_META(*cfg_global, group), group,
1632 /* fill in the new group instance with the default data */
1633 memcpy( new_inst->vars,
1634 CFG_GROUP_DATA(*cfg_global, group),
1637 CFG_GROUP_META(block, group)->array = new_array;
1638 CFG_GROUP_META(block, group)->num++;
1640 if (CFG_GROUP_META(*cfg_global, group)->array) {
1641 /* prepare the array of the replaced strings,
1642 * and replaced group instances,
1643 * they will be freed when the old block is freed */
1644 replaced = (void **)shm_malloc(sizeof(void *) * 2);
1649 replaced[0] = CFG_GROUP_META(*cfg_global, group)->array;
1652 /* replace the global config with the new one */
1653 cfg_install_global(block, replaced, NULL, NULL);
1654 CFG_WRITER_UNLOCK();
1656 LM_INFO("group instance is added: %.*s[%u]\n",
1657 group_name->len, group_name->s,
1660 /* Make sure that cfg_set_*() sees the change when
1661 * the function is immediately called after the group
1662 * instance has been added. */
1667 CFG_WRITER_UNLOCK();
1668 if (block) cfg_block_free(block);
1669 if (new_array) shm_free(new_array);
1670 if (replaced) shm_free(replaced);
1672 LM_ERR("Failed to add the group instance: %.*s[%u]\n",
1673 group_name->len, group_name->s,
1679 /* Delete an instance of a group */
1680 int cfg_del_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id)
1683 cfg_block_t *block = NULL;
1684 void **replaced = NULL;
1685 cfg_group_inst_t *new_array = NULL, *group_inst;
1689 /* verify the context even if we do not need it now
1690 * to make sure that a cfg driver has called the function
1691 * (very very weak security) */
1693 LM_ERR("context is undefined\n");
1698 /* It makes no sense to delete a group instance that has not
1699 * been created yet */
1703 if (!(group = cfg_lookup_group(group_name->s, group_name->len))) {
1704 LM_ERR("group not found\n");
1708 /* make sure that nobody else replaces the global config
1709 * while the new one is prepared */
1711 if (!(group_inst = cfg_find_group(CFG_GROUP_META(*cfg_global, group),
1715 LM_DBG("the group instance does not exist\n");
1719 /* clone the global memory block because the additional array can be
1720 * replaced only together with the block. */
1721 if (!(block = cfg_clone_global()))
1724 /* Remove the group instance from the array. */
1725 if (cfg_collapse_array(CFG_GROUP_META(*cfg_global, group), group,
1730 CFG_GROUP_META(block, group)->array = new_array;
1731 CFG_GROUP_META(block, group)->num--;
1733 if (CFG_GROUP_META(*cfg_global, group)->array) {
1734 /* prepare the array of the replaced strings,
1735 * and replaced group instances,
1736 * they will be freed when the old block is freed */
1738 /* count the number of strings that has to be freed */
1740 for (i = 0; i < group->num; i++) {
1741 var = &group->mapping[i];
1742 if (CFG_VAR_TEST(group_inst, var)
1743 && ((CFG_VAR_TYPE(var) == CFG_VAR_STRING)
1744 || (CFG_VAR_TYPE(var) == CFG_VAR_STR))
1745 && (*(char **)(group_inst->vars + var->offset) != NULL))
1749 replaced = (void **)shm_malloc(sizeof(void *) * (num + 2));
1756 /* There was at least one string to free, go though the list again */
1758 for (i = 0; i < group->num; i++) {
1759 var = &group->mapping[i];
1760 if (CFG_VAR_TEST(group_inst, var)
1761 && ((CFG_VAR_TYPE(var) == CFG_VAR_STRING)
1762 || (CFG_VAR_TYPE(var) == CFG_VAR_STR))
1763 && (*(char **)(group_inst->vars + var->offset) != NULL)
1765 replaced[num] = *(char **)(group_inst->vars + var->offset);
1771 replaced[num] = CFG_GROUP_META(*cfg_global, group)->array;
1772 replaced[num+1] = NULL;
1774 /* replace the global config with the new one */
1775 cfg_install_global(block, replaced, NULL, NULL);
1776 CFG_WRITER_UNLOCK();
1778 LM_INFO("group instance is deleted: %.*s[%u]\n",
1779 group_name->len, group_name->s,
1782 /* Make sure that cfg_set_*() sees the change when
1783 * the function is immediately called after the group
1784 * instance has been deleted. */
1789 CFG_WRITER_UNLOCK();
1790 if (block) cfg_block_free(block);
1791 if (new_array) shm_free(new_array);
1792 if (replaced) shm_free(replaced);
1794 LM_ERR("Failed to delete the group instance: %.*s[%u]\n",
1795 group_name->len, group_name->s,
1801 /* Check the existance of a group instance.
1806 int cfg_group_inst_exists(cfg_ctx_t *ctx, str *group_name, unsigned int group_id)
1809 cfg_add_var_t *add_var;
1812 /* verify the context even if we do not need it now
1813 * to make sure that a cfg driver has called the function
1814 * (very very weak security) */
1816 LM_ERR("context is undefined\n");
1820 if (!(group = cfg_lookup_group(group_name->s, group_name->len))) {
1821 LM_ERR("group not found\n");
1826 /* group instances are stored in the additional variable list
1829 for (add_var = group->add_var;
1831 add_var = add_var->next
1833 if (add_var->group_id == group_id) {
1839 /* make sure that nobody else replaces the global config meantime */
1841 found = (cfg_find_group(CFG_GROUP_META(*cfg_global, group),
1845 CFG_WRITER_UNLOCK();
1851 /* Apply the changes to a group instance as long as the additional variable
1852 * belongs to the specified group_id. *add_var_p is moved to the next additional
1853 * variable, and all the consumed variables are freed.
1854 * This function can be used only during the cfg shmize process.
1855 * For internal use only!
1857 int cfg_apply_list(cfg_group_inst_t *ginst, cfg_group_t *group,
1858 unsigned int group_id, cfg_add_var_t **add_var_p)
1860 cfg_add_var_t *add_var;
1863 str group_name, var_name, s;
1866 group_name.s = group->name;
1867 group_name.len = group->name_len;
1868 while (*add_var_p && ((*add_var_p)->group_id == group_id)) {
1869 add_var = *add_var_p;
1871 if (add_var->type == 0)
1872 goto done; /* Nothing needs to be changed,
1873 * this additional variable only forces a new
1874 * group instance to be created. */
1875 var_name.s = add_var->name;
1876 var_name.len = add_var->name_len;
1878 if (!(var = cfg_lookup_var2(group, add_var->name, add_var->name_len))) {
1879 LM_ERR("Variable is not found: %.*s.%.*s\n",
1880 group->name_len, group->name,
1881 add_var->name_len, add_var->name);
1885 /* check whether the variable is read-only */
1886 if (var->def->type & CFG_READONLY) {
1887 LM_ERR("variable is read-only\n");
1891 /* The additional variable instances having per-child process callback
1892 * with CFG_CB_ONLY_ONCE flag cannot be rewritten.
1893 * The reason is that such variables typically set global parameters
1894 * as opposed to per-process variables. Hence, it is not possible to set
1895 * the group handle temporary to another block, and then reset it back later. */
1896 if (var->def->on_set_child_cb
1897 && var->def->type & CFG_CB_ONLY_ONCE
1899 LM_ERR("This variable does not support muliple values.\n");
1903 switch(add_var->type) {
1905 val = (void *)(long)add_var->val.i;
1908 val = (str *)&(add_var->val.s);
1910 case CFG_VAR_STRING:
1911 val = (char *)add_var->val.ch;
1914 LM_ERR("unsupported variable type: %d\n",
1918 /* check whether we have to convert the type */
1919 if (convert_val(add_var->type, val, CFG_INPUT_TYPE(var), &v))
1922 if ((CFG_INPUT_TYPE(var) == CFG_INPUT_INT)
1923 && (var->def->min || var->def->max)) {
1924 /* perform a simple min-max check for integers */
1925 if (((int)(long)v < var->def->min)
1926 || ((int)(long)v > var->def->max)) {
1927 LM_ERR("integer value is out of range\n");
1932 if (var->def->on_change_cb) {
1933 /* Call the fixup function.
1934 * The handle can point to the variables of the group instance. */
1935 if (var->def->on_change_cb(ginst->vars,
1939 LM_ERR("fixup failed\n");
1944 p = ginst->vars + var->offset;
1946 /* set the new value */
1947 switch (CFG_VAR_TYPE(var)) {
1949 *(int *)p = (int)(long)v;
1952 case CFG_VAR_STRING:
1953 /* clone the string to shm mem */
1955 s.len = (s.s) ? strlen(s.s) : 0;
1956 if (cfg_clone_str(&s, &s)) goto error;
1957 old_string = *(char **)p;
1962 /* clone the string to shm mem */
1964 if (cfg_clone_str(&s, &s)) goto error;
1965 old_string = *(char **)p;
1966 memcpy(p, &s, sizeof(str));
1969 case CFG_VAR_POINTER:
1974 if (CFG_VAR_TEST_AND_SET(ginst, var) && old_string)
1975 shm_free(old_string); /* the string was already in shm memory,
1976 * it needs to be freed.
1977 * This can happen when the same variable is set
1978 * multiple times before forking. */
1980 if (add_var->type == CFG_VAR_INT)
1981 LM_INFO("%.*s[%u].%.*s has been set to %d\n",
1982 group_name.len, group_name.s,
1984 var_name.len, var_name.s,
1987 else if (add_var->type == CFG_VAR_STRING)
1988 LM_INFO("%.*s[%u].%.*s has been set to \"%s\"\n",
1989 group_name.len, group_name.s,
1991 var_name.len, var_name.s,
1995 LM_INFO("%.*s[%u].%.*s has been set to \"%.*s\"\n",
1996 group_name.len, group_name.s,
1998 var_name.len, var_name.s,
1999 ((str *)val)->len, ((str *)val)->s);
2001 convert_val_cleanup();
2004 *add_var_p = add_var->next;
2006 if ((add_var->type == CFG_VAR_STR) && add_var->val.s.s)
2007 pkg_free(add_var->val.s.s);
2008 else if ((add_var->type == CFG_VAR_STRING) && add_var->val.ch)
2009 pkg_free(add_var->val.ch);
2015 LM_ERR("Failed to set the value for: %.*s[%u].%.*s\n",
2016 group->name_len, group->name,
2018 add_var->name_len, add_var->name);
2019 convert_val_cleanup();