Coverage Report

Created: 2024-02-25 06:34

/src/kamailio/src/core/cfg/cfg_struct.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2007 iptelorg GmbH
3
 *
4
 * This file is part of Kamailio, a free SIP server.
5
 *
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
10
 *
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.
15
 *
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
19
 *
20
 */
21
22
#ifndef _CFG_STRUCT_H
23
#define _CFG_STRUCT_H
24
25
#include "../str.h"
26
#include "../atomic_ops.h"
27
#include "../mem/shm_mem.h"
28
#include "../locking.h"
29
#include "../compiler_opt.h"
30
#include "../bit_test.h"
31
#include "cfg.h"
32
33
/*! \brief Maximum number of variables within a configuration group. */
34
0
#define CFG_MAX_VAR_NUM 256
35
36
/*! \brief indicates that the variable has been already shmized */
37
0
#define cfg_var_shmized 1U
38
39
/*! \brief Structure for storing additional values of a variable.
40
 * When the config is shmzied, these variables are combined in
41
 * an array.
42
 */
43
#pragma pack(push, 1)
44
typedef struct _cfg_add_var
45
{
46
  struct _cfg_add_var *next;
47
  unsigned int type; /*!< type == 0 is also valid, it indicates that the group
48
        must be created with the default values */
49
  unsigned int group_id; /*!< Id of the group instance */
50
  union
51
  {
52
    char *ch;
53
    str s;
54
    int i;
55
  } val;
56
  int name_len; /*!< Name of the variable. The variable may not be known,
57
          for example the additional group value is set in the script
58
          before the cfg group is declared. Hence, the pointer cannot
59
          be stored here. */
60
  char name[1];
61
} cfg_add_var_t;
62
#pragma pack(pop)
63
64
/*! \brief structure used for variable - pointer mapping */
65
typedef struct _cfg_mapping
66
{
67
  cfg_def_t *def; /*!< one item of the cfg structure definition */
68
  int name_len; /*!< length of def->name */
69
70
  /* additional information about the cfg variable */
71
  int pos; /*!< position of the variable within the group starting from 0 */
72
  int offset;      /*!< offest within the memory block */
73
  unsigned int flag; /*!< flag indicating the state of the variable */
74
} cfg_mapping_t;
75
76
/*! \brief type of the group */
77
enum
78
{
79
  CFG_GROUP_UNKNOWN = 0,
80
  CFG_GROUP_DYNAMIC,
81
  CFG_GROUP_STATIC
82
};
83
84
/*! \brief linked list of registered groups */
85
#pragma pack(push, 1)
86
typedef struct _cfg_group
87
{
88
  cfg_mapping_t *mapping; /*!< describes the mapping betweeen
89
          the cfg variable definition and the memory block */
90
  char *vars;       /*!< pointer to the memory block where the values
91
          are stored -- used only before the config is
92
          shmized. */
93
  cfg_add_var_t *add_var; /*!< Additional instances of the variables.
94
          This linked list is used only before the config is
95
          shmized. */
96
  int num;        /*!< number of variables within the group */
97
  int size;       /*!< size of the memory block that has to be
98
          allocated to store the values */
99
  int meta_offset;    /*!< offset of the group within the
100
          shmized memory block for the meta_data */
101
  int var_offset;     /*!< offset of the group within the
102
          shmized memory block for the variables */
103
  void **handle;      /*!< per-process handle that can be used
104
          by the modules to access the variables.
105
          It is registered when the group is created,
106
          and updated every time the block is replaced */
107
  void *orig_handle;    /*!< Original value that the handle points to
108
          when the config group is registered. This is needed
109
          to temporary set the handle in the main process and
110
          restore it later to its original value. */
111
112
  struct _cfg_group *next;
113
  unsigned int dynamic; /*!< indicates whether the variables within the group
114
          are dynamically allocated or not */
115
  int name_len;
116
  char name[1];
117
} cfg_group_t;
118
#pragma pack(pop)
119
120
/*! \brief One instance of the cfg group variables which stores
121
 * the additional values. These values can overwrite the default values. */
122
#pragma pack(push, 1)
123
typedef struct _cfg_group_inst
124
{
125
  unsigned int id; /*!< identifier of the group instance */
126
  unsigned int set[CFG_MAX_VAR_NUM / (sizeof(int) * 8)];
127
  /*!< Bitmap indicating whether or not a value is explicitely set
128
          within this instance. If the value is not set,
129
          then the default value is used, and copied into this instance. */
130
  unsigned char vars[1]; /*!< block for the values */
131
} cfg_group_inst_t;
132
#pragma pack(pop)
133
134
/*! \brief Meta-data which is stored before each variable group
135
 * within the blob. This structure is used to handle the multivalue
136
 * instances of the variables, i.e. manages the array for the
137
 * additional values. */
138
typedef struct _cfg_group_meta
139
{
140
  int num; /*!< Number of items in the array */
141
  cfg_group_inst_t
142
      *array; /*!< Array of cfg groups with num number of items */
143
} cfg_group_meta_t;
144
145
/*! \brief single memory block that contains all the cfg values */
146
#pragma pack(push, 1)
147
typedef struct _cfg_block
148
{
149
  atomic_t refcnt;     /*!< reference counter,
150
          the block is automatically deleted
151
          when it reaches 0 */
152
  int _pad;        /*!< force 8 byte alignment */
153
  unsigned char vars[1]; /*!< blob that contains the values */
154
} cfg_block_t;
155
#pragma pack(pop)
156
157
/*! \brief Linked list of per-child process callbacks.
158
 * Each child process has a local pointer, and executes the callbacks
159
 * when the pointer is not pointing to the end of the list.
160
 * Items from the begginning of the list are deleted when the starter
161
 * pointer is moved, and no more child process uses them.
162
 */
163
typedef struct _cfg_child_cb
164
{
165
  atomic_t refcnt;   /*!< number of child processes
166
          referring to the element */
167
  atomic_t cb_count;   /*!< This counter is used to track
168
             * how many times the callback needs
169
             * to be executed.
170
             * >0 the cb needs to be executed
171
             * <=0 the cb no longer needs to be executed
172
             */
173
  str gname, name;   /*!< name of the variable that has changed */
174
  cfg_on_set_child cb; /*!< callback function that has to be called */
175
  void **replaced;   /*!< set of strings and other memory segments
176
            that must be freed together with this structure.
177
            The content depends on the new config block.
178
            This makes sure that the replaced strings are freed
179
            after all the child processes release the old configuration. */
180
181
  struct _cfg_child_cb *next;
182
} cfg_child_cb_t;
183
184
extern cfg_group_t *cfg_group;
185
extern cfg_block_t **cfg_global;
186
extern cfg_block_t *cfg_local;
187
extern int cfg_block_size;
188
extern gen_lock_t *cfg_global_lock;
189
extern gen_lock_t *cfg_writer_lock;
190
extern int cfg_shmized;
191
extern cfg_child_cb_t **cfg_child_cb_first;
192
extern cfg_child_cb_t **cfg_child_cb_last;
193
extern cfg_child_cb_t *cfg_child_cb;
194
extern int cfg_ginst_count;
195
196
/* magic value for cfg_child_cb for processes that do not want to
197
   execute per-child callbacks */
198
0
#define CFG_NO_CHILD_CBS ((void *)(long)(-1))
199
200
/* macros for easier variable access */
201
0
#define CFG_VAR_TYPE(var) CFG_VAR_MASK((var)->def->type)
202
0
#define CFG_INPUT_TYPE(var) CFG_INPUT_MASK((var)->def->type)
203
204
/* get the meta-data of a group from the block */
205
#define CFG_GROUP_META(block, group) \
206
0
  ((cfg_group_meta_t *)((block)->vars + (group)->meta_offset))
207
208
/* get the data block of a group from the block */
209
#define CFG_GROUP_DATA(block, group) \
210
0
  ((unsigned char *)((block)->vars + (group)->var_offset))
211
212
/* Test whether a variable is explicitely set in the group instance,
213
 * or it uses the default value */
214
#define CFG_VAR_TEST(group_inst, var)        \
215
0
  bit_test((var)->pos % (sizeof(int) * 8), \
216
0
      (group_inst)->set + (var)->pos / (sizeof(int) * 8))
217
218
/* Test whether a variable is explicitely set in the group instance,
219
 * or it uses the default value, and set the flag. */
220
#define CFG_VAR_TEST_AND_SET(group_inst, var)        \
221
0
  bit_test_and_set((var)->pos % (sizeof(int) * 8), \
222
0
      (group_inst)->set + (var)->pos / (sizeof(int) * 8))
223
224
/* Test whether a variable is explicitely set in the group instance,
225
 * or it uses the default value, and reset the flag. */
226
#define CFG_VAR_TEST_AND_RESET(group_inst, var)        \
227
0
  bit_test_and_reset((var)->pos % (sizeof(int) * 8), \
228
0
      (group_inst)->set + (var)->pos / (sizeof(int) * 8))
229
230
/* Return the group instance pointer from a handle,
231
 * or NULL if the handle points to the default configuration block */
232
#define CFG_HANDLE_TO_GINST(h)                                             \
233
0
  ((((unsigned char *)(h) < cfg_local->vars)                             \
234
0
       || ((unsigned char *)(h) > cfg_local->vars + cfg_block_size)) \
235
0
          ? (cfg_group_inst_t *)((char *)(h)                     \
236
0
                       - (unsigned long)&(             \
237
0
                           (cfg_group_inst_t *)0)  \
238
0
                           ->vars)               \
239
0
          : NULL)
240
241
/* initiate the cfg framework */
242
int sr_cfg_init(void);
243
244
/* destroy the memory allocated for the cfg framework */
245
void cfg_destroy(void);
246
247
/* Register num number of child processes that will
248
 * keep updating their local configuration.
249
 * This function needs to be called from mod_init
250
 * before any child process is forked.
251
 */
252
void cfg_register_child(int num);
253
254
/* per-child process init function.
255
 * It needs to be called from the forked process.
256
 * cfg_register_child() must be called before this function!
257
 */
258
int cfg_child_init(void);
259
260
/* Child process init function that can be called
261
 * without cfg_register_child().
262
 * Note that the child process may miss some configuration changes.
263
 */
264
int cfg_late_child_init(void);
265
266
/* per-child init function for non-cb executing processes.
267
 * Mark this process as not wanting to execute any per-child config
268
 * callback (it will have only limited config functionality, but is useful
269
 * when a process needs only to watch some non-callback cfg. values,
270
 * e.g. the main attendant process, debug and memlog).
271
 * It needs to be called from the forked process.
272
 * cfg_register_child must _not_ be called.
273
 */
274
int cfg_child_no_cb_init(void);
275
276
/* per-child process destroy function
277
 * Should be called only when the child process exits,
278
 * but SER continues running.
279
 *
280
 * WARNING: this function call must be the very last action
281
 * before the child process exits, because the local config
282
 * is not available afterwards.
283
 */
284
void cfg_child_destroy(void);
285
286
/* creates a new cfg group, and adds it to the linked list */
287
cfg_group_t *cfg_new_group(char *name, int name_len, int num,
288
    cfg_mapping_t *mapping, char *vars, int size, void **handle);
289
290
/* Set the values of an existing cfg group. */
291
void cfg_set_group(cfg_group_t *group, int num, cfg_mapping_t *mapping,
292
    char *vars, int size, void **handle);
293
294
/* copy the variables to shm mem */
295
int cfg_shmize(void);
296
297
/* free the memory of a child cb structure */
298
static inline void cfg_child_cb_free_item(cfg_child_cb_t *cb)
299
0
{
300
0
  int i;
301
302
  /* free the changed variables */
303
0
  if(cb->replaced) {
304
0
    for(i = 0; cb->replaced[i]; i++)
305
0
      shm_free(cb->replaced[i]);
306
0
    shm_free(cb->replaced);
307
0
  }
308
0
  shm_free(cb);
309
0
}
Unexecuted instantiation: main.c:cfg_child_cb_free_item
Unexecuted instantiation: route.c:cfg_child_cb_free_item
Unexecuted instantiation: tcp_main.c:cfg_child_cb_free_item
Unexecuted instantiation: tcp_read.c:cfg_child_cb_free_item
Unexecuted instantiation: timer.c:cfg_child_cb_free_item
Unexecuted instantiation: timer_proc.c:cfg_child_cb_free_item
Unexecuted instantiation: udp_server.c:cfg_child_cb_free_item
Unexecuted instantiation: action.c:cfg_child_cb_free_item
Unexecuted instantiation: async_task.c:cfg_child_cb_free_item
Unexecuted instantiation: cfg.c:cfg_child_cb_free_item
Unexecuted instantiation: cfg_ctx.c:cfg_child_cb_free_item
Unexecuted instantiation: cfg_script.c:cfg_child_cb_free_item
Unexecuted instantiation: cfg_select.c:cfg_child_cb_free_item
Unexecuted instantiation: cfg_struct.c:cfg_child_cb_free_item
310
311
0
#define cfg_block_free(block) shm_free(block)
312
313
/* Move the group handle to the specified group instance pointed by dst_ginst.
314
 * src_ginst shall point to the active group instance.
315
 * Both parameters can be NULL meaning that the src/dst config is the default,
316
 * not an additional group instance.
317
 * The function executes all the per-child process callbacks which are different
318
 * in the two instances.
319
 */
320
void cfg_move_handle(cfg_group_t *group, cfg_group_inst_t *src_ginst,
321
    cfg_group_inst_t *dst_ginst);
322
323
324
/* lock and unlock the global cfg block -- used only at the
325
 * very last step when the block is replaced */
326
0
#define CFG_LOCK() lock_get(cfg_global_lock);
327
0
#define CFG_UNLOCK() lock_release(cfg_global_lock);
328
329
/* lock and unlock used by the cfg drivers to make sure that
330
 * only one driver process is considering replacing the global
331
 * cfg block */
332
0
#define CFG_WRITER_LOCK() lock_get(cfg_writer_lock);
333
0
#define CFG_WRITER_UNLOCK() lock_release(cfg_writer_lock);
334
335
/* increase and decrease the reference counter of a block */
336
0
#define CFG_REF(block) atomic_inc(&(block)->refcnt)
337
338
#define CFG_UNREF(block)                          \
339
0
  do {                                          \
340
0
    if(atomic_dec_and_test(&(block)->refcnt)) \
341
0
      cfg_block_free(block);                \
342
0
  } while(0)
343
344
/* updates all the module handles and calls the
345
 * per-child process callbacks -- not intended to be used
346
 * directly, use cfg_update() instead!
347
 * params:
348
 *   no_cbs - if 1, do not call per child callbacks
349
 */
350
static inline void cfg_update_local(int no_cbs)
351
0
{
352
0
  cfg_group_t *group;
353
0
  cfg_child_cb_t *last_cb;
354
0
  cfg_child_cb_t *prev_cb;
355
356
0
  if(cfg_local)
357
0
    CFG_UNREF(cfg_local);
358
0
  CFG_LOCK();
359
0
  CFG_REF(*cfg_global);
360
0
  cfg_local = *cfg_global;
361
  /* the value of the last callback must be read within the lock */
362
0
  last_cb = *cfg_child_cb_last;
363
364
  /* I unlock now, because the child process can update its own private
365
  config without the lock held. In the worst case, the process will get the
366
  lock once more to set cfg_child_cb_first, but only one of the child
367
  processes will do so, and only if a value, that has per-child process
368
  callback defined, was changed. */
369
0
  CFG_UNLOCK();
370
371
  /* update the handles */
372
0
  for(group = cfg_group; group; group = group->next)
373
0
    *(group->handle) = CFG_GROUP_DATA(cfg_local, group);
374
375
0
  if(unlikely(cfg_child_cb == CFG_NO_CHILD_CBS || no_cbs))
376
0
    return;
377
  /* call the per-process callbacks */
378
0
  while(cfg_child_cb != last_cb) {
379
0
    prev_cb = cfg_child_cb;
380
0
    cfg_child_cb = cfg_child_cb->next;
381
0
    atomic_inc(&cfg_child_cb->refcnt);
382
0
    if(atomic_dec_and_test(&prev_cb->refcnt)) {
383
      /* No more pocess refers to this callback.
384
      Did this process block the deletion,
385
      or is there any other process that has not
386
      reached prev_cb yet? */
387
0
      CFG_LOCK();
388
0
      if(*cfg_child_cb_first == prev_cb) {
389
        /* yes, this process was blocking the deletion */
390
0
        *cfg_child_cb_first = cfg_child_cb;
391
0
        CFG_UNLOCK();
392
0
        cfg_child_cb_free_item(prev_cb);
393
0
      } else {
394
0
        CFG_UNLOCK();
395
0
      }
396
0
    }
397
0
    if(cfg_child_cb->cb
398
0
        && (atomic_add(&cfg_child_cb->cb_count, -1)
399
0
            >= 0) /* the new value is returned
400
                  by atomic_add() */
401
0
    )
402
      /* execute the callback */
403
0
      cfg_child_cb->cb(&cfg_child_cb->gname, &cfg_child_cb->name);
404
    /* else the callback no longer needs to be executed */
405
0
  }
406
0
}
Unexecuted instantiation: main.c:cfg_update_local
Unexecuted instantiation: route.c:cfg_update_local
Unexecuted instantiation: tcp_main.c:cfg_update_local
Unexecuted instantiation: tcp_read.c:cfg_update_local
Unexecuted instantiation: timer.c:cfg_update_local
Unexecuted instantiation: timer_proc.c:cfg_update_local
Unexecuted instantiation: udp_server.c:cfg_update_local
Unexecuted instantiation: action.c:cfg_update_local
Unexecuted instantiation: async_task.c:cfg_update_local
Unexecuted instantiation: cfg.c:cfg_update_local
Unexecuted instantiation: cfg_ctx.c:cfg_update_local
Unexecuted instantiation: cfg_script.c:cfg_update_local
Unexecuted instantiation: cfg_select.c:cfg_update_local
Unexecuted instantiation: cfg_struct.c:cfg_update_local
407
408
/* Reset all the group handles to the default, local configuration */
409
static inline void cfg_reset_handles(void)
410
0
{
411
0
  cfg_group_t *group;
412
413
0
  if(!cfg_local)
414
0
    return;
415
416
0
  for(group = cfg_group;
417
0
      group && cfg_ginst_count; /* cfg_ginst_count is decreased every time
418
          a group handle is reset. When it reaches 0,
419
          needless to continue the loop */
420
0
      group = group->next) {
421
0
    if(((unsigned char *)*(group->handle) < cfg_local->vars)
422
0
        || ((unsigned char *)*(group->handle)
423
0
            > cfg_local->vars + cfg_block_size))
424
0
      cfg_move_handle(group, CFG_HANDLE_TO_GINST(*(group->handle)), NULL);
425
0
  }
426
0
}
Unexecuted instantiation: main.c:cfg_reset_handles
Unexecuted instantiation: route.c:cfg_reset_handles
Unexecuted instantiation: tcp_main.c:cfg_reset_handles
Unexecuted instantiation: tcp_read.c:cfg_reset_handles
Unexecuted instantiation: timer.c:cfg_reset_handles
Unexecuted instantiation: timer_proc.c:cfg_reset_handles
Unexecuted instantiation: udp_server.c:cfg_reset_handles
Unexecuted instantiation: action.c:cfg_reset_handles
Unexecuted instantiation: async_task.c:cfg_reset_handles
Unexecuted instantiation: cfg.c:cfg_reset_handles
Unexecuted instantiation: cfg_ctx.c:cfg_reset_handles
Unexecuted instantiation: cfg_script.c:cfg_reset_handles
Unexecuted instantiation: cfg_select.c:cfg_reset_handles
Unexecuted instantiation: cfg_struct.c:cfg_reset_handles
427
428
/* sets the local cfg block to the active block
429
 *
430
 * If your module forks a new process that implements
431
 * an infinite loop, put cfg_update() to the beginning of
432
 * the cycle to make sure, that subsequent function calls see the
433
 * up-to-date config set.
434
 */
435
#define cfg_update()                           \
436
0
  do {                                       \
437
0
    if(unlikely(cfg_ginst_count))          \
438
0
      cfg_reset_handles();               \
439
0
    if(unlikely(cfg_local != *cfg_global)) \
440
0
      cfg_update_local(0);               \
441
0
  } while(0)
442
443
/* like cfg_update(), but does not execute callbacks
444
 * (it should be used sparingly only in special cases, since it
445
 *  breaks an important cfg framework feature)
446
 */
447
#define cfg_update_no_cbs()                    \
448
0
  do {                                       \
449
0
    if(unlikely(cfg_local != *cfg_global)) \
450
0
      cfg_update_local(1);               \
451
0
  } while(0)
452
453
/* Reset all the group handles in the child process,
454
 * i.e. move them back to the default local configuration.
455
 */
456
#define cfg_reset_all()               \
457
0
  do {                              \
458
0
    if(unlikely(cfg_ginst_count)) \
459
0
      cfg_reset_handles();      \
460
0
  } while(0)
461
462
463
/* searches a group by name */
464
cfg_group_t *cfg_lookup_group(char *name, int len);
465
466
/* searches a variable definition by group and variable name */
467
int cfg_lookup_var(
468
    str *gname, str *vname, cfg_group_t **group, cfg_mapping_t **var);
469
470
/* searches a variable definition within a group by its name */
471
cfg_mapping_t *cfg_lookup_var2(cfg_group_t *group, char *name, int len);
472
473
/* clones the global config block
474
 * WARNING: unsafe, cfg_writer_lock or cfg_global_lock must be held!
475
 */
476
cfg_block_t *cfg_clone_global(void);
477
478
/* Clone an array of configuration group instances. */
479
cfg_group_inst_t *cfg_clone_array(cfg_group_meta_t *meta, cfg_group_t *group);
480
481
/* Extend the array of configuration group instances with one more instance.
482
 * Only the ID of the new group is set, nothing else. */
483
cfg_group_inst_t *cfg_extend_array(cfg_group_meta_t *meta, cfg_group_t *group,
484
    unsigned int group_id, cfg_group_inst_t **new_group);
485
486
/* Remove an instance from a group array.
487
 * inst must point to an instance within meta->array.
488
 * *_new_array is set to the newly allocated array. */
489
int cfg_collapse_array(cfg_group_meta_t *meta, cfg_group_t *group,
490
    cfg_group_inst_t *inst, cfg_group_inst_t **_new_array);
491
492
/* clones a string to shared memory */
493
int cfg_clone_str(str *src, str *dst);
494
495
/* Find the group instance within the meta-data based on the group_id */
496
cfg_group_inst_t *cfg_find_group(
497
    cfg_group_meta_t *meta, int group_size, unsigned int group_id);
498
499
/* append new callbacks to the end of the child callback list
500
 *
501
 * WARNING: the function is unsafe, either hold CFG_LOCK(),
502
 * or call the function before forking
503
 */
504
void cfg_install_child_cb(cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last);
505
506
/* installs a new global config
507
 *
508
 * replaced is an array of strings that must be freed together
509
 * with the previous global config.
510
 * cb_first and cb_last define a linked list of per-child process
511
 * callbacks. This list is added to the global linked list.
512
 */
513
void cfg_install_global(cfg_block_t *block, void **replaced,
514
    cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last);
515
516
/* creates a structure for a per-child process callback */
517
cfg_child_cb_t *cfg_child_cb_new(
518
    str *gname, str *name, cfg_on_set_child cb, unsigned int type);
519
520
/* free the memory allocated for a child cb list */
521
void cfg_child_cb_free_list(cfg_child_cb_t *child_cb_first);
522
523
/* Allocate memory for a new additional variable
524
 * and link it to a configuration group.
525
 * type==0 results in creating a new group instance with the default values.
526
 * The group is created with CFG_GROUP_UNKNOWN type if it does not exist.
527
 * Note: this function is usable only before the configuration is shmized.
528
 */
529
int new_add_var(str *group_name, unsigned int group_id, str *var_name,
530
    void *val, unsigned int type);
531
532
/* Move the group handle to the specified group instance. */
533
int cfg_select(cfg_group_t *group, unsigned int id);
534
535
/* Reset the group handle to the default, local configuration */
536
int cfg_reset(cfg_group_t *group);
537
538
/* Move the group handle to the first group instance.
539
 * This function together with cfg_select_next() can be used
540
 * to iterate though the list of instances.
541
 *
542
 * Return value:
543
 *  -1: no group instance found
544
 *   0: first group instance is successfully selected.
545
 */
546
int cfg_select_first(cfg_group_t *group);
547
548
/* Move the group handle to the next group instance.
549
 * This function together with cfg_select_first() can be used
550
 * to iterate though the list of instances.
551
 *
552
 * Return value:
553
 *  -1: no more group instance found. Note, that the active group
554
 *    instance is not changed in this case.
555
 *   0: the next group instance is successfully selected.
556
 */
557
int cfg_select_next(cfg_group_t *group);
558
559
/* Temporary set the local configuration in the main process before forking.
560
 * This makes the group instances usable in the main process after
561
 * the configuration is shmized, but before the children are forked.
562
 */
563
void cfg_main_set_local(void);
564
565
/* Reset the local configuration of the main process back to its original state
566
 * to make sure that the forked processes are not affected.
567
 */
568
void cfg_main_reset_local(void);
569
570
#endif /* _CFG_STRUCT_H */