all: updated FSF address in GPL text
[sip-router] / modules / pv / pv_shv.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2007 Elena-Ramona Modroiu
5  * Copyright (C) 2013 Olle E. Johansson
6  *
7  * This file is part of Kamailio, a free SIP server.
8  *
9  * Kamailio is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version
13  *
14  * Kamailio is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License 
20  * along with this program; if not, write to the Free Software 
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #include <assert.h>
26 #include <ctype.h>
27 #include <string.h>
28 #include <stdlib.h>
29
30 #include "../../dprint.h"
31 #include "../../mem/mem.h"
32 #include "../../mem/shm_mem.h"
33 #include "../../shm_init.h"
34 #include "../../ut.h"
35 #include "../../pvar.h"
36
37 #include "pv_shv.h"
38
39 int shvar_locks_no=16;
40 gen_lock_set_t* shvar_locks=0;
41
42 static sh_var_t *sh_vars = 0;
43 static str shv_cpy = {0, 0};
44
45 /*
46  * Initialize locks
47  */
48 int shvar_init_locks(void)
49 {
50         int i;
51
52         /* already initialized */
53         if(shvar_locks!=0)
54                 return 0;
55
56         i = shvar_locks_no;
57         do {
58                 if ((( shvar_locks=lock_set_alloc(i))!=0)&&
59                                 (lock_set_init(shvar_locks)!=0))
60                 {
61                         shvar_locks_no = i;
62                         LM_INFO("locks array size %d\n", shvar_locks_no);
63                         return 0;
64
65                 }
66                 if (shvar_locks){
67                         lock_set_dealloc(shvar_locks);
68                         shvar_locks=0;
69                 }
70                 i--;
71                 if(i==0)
72                 {
73                         LM_ERR("failed to allocate locks\n");
74                         return -1;
75                 }
76         } while (1);
77 }
78
79
80 void shvar_unlock_locks(void)
81 {
82         unsigned int i;
83
84         if (shvar_locks==0)
85                 return;
86
87         for (i=0;i<shvar_locks_no;i++) {
88 #ifdef GEN_LOCK_T_PREFERED
89                 lock_release(&shvar_locks->locks[i]);
90 #else
91                 shvar_release_idx(i);
92 #endif
93         };
94 }
95
96
97 void shvar_destroy_locks(void)
98 {
99         if (shvar_locks !=0){
100                 lock_set_destroy(shvar_locks);
101                 lock_set_dealloc(shvar_locks);
102         }
103 }
104
105 #ifndef GEN_LOCK_T_PREFERED
106 void shvar_lock_idx(int idx)
107 {
108         lock_set_get(shvar_locks, idx);
109 }
110
111 void shvar_release_idx(int idx)
112 {
113         lock_set_release(shvar_locks, idx);
114 }
115 #endif
116
117 /*
118  * Get lock
119  */
120 void lock_shvar(sh_var_t *shv)
121 {
122         if(shv==NULL)
123                 return;
124 #ifdef GEN_LOCK_T_PREFERED
125         lock_get(shv->lock);
126 #else
127         ul_lock_idx(shv->lockidx);
128 #endif
129 }
130
131
132 /*
133  * Release lock
134  */
135 void unlock_shvar(sh_var_t *shv)
136 {
137         if(shv==NULL)
138                 return;
139 #ifdef GEN_LOCK_T_PREFERED
140         lock_release(shv->lock);
141 #else
142         ul_release_idx(shv->lockidx);
143 #endif
144 }
145
146
147 sh_var_t* add_shvar(str *name)
148 {
149         sh_var_t *sit;
150
151         if(name==0 || name->s==0 || name->len<=0)
152                 return 0;
153
154         if(!shm_initialized())
155         {
156                 LM_ERR("shm not intialized - cannot define shm now\n");
157                 return 0;
158         }
159
160         if(shvar_init_locks()!=0)
161         {
162                 LM_ERR("cannot init shv locks\n");
163                 return 0;
164         }
165
166         for(sit=sh_vars; sit; sit=sit->next)
167         {
168                 if(sit->name.len==name->len
169                                 && strncmp(name->s, sit->name.s, name->len)==0)
170                         return sit;
171         }
172         sit = (sh_var_t*)shm_malloc(sizeof(sh_var_t));
173         if(sit==0)
174         {
175                 LM_ERR("out of shm\n");
176                 return 0;
177         }
178         memset(sit, 0, sizeof(sh_var_t));
179         sit->name.s = (char*)shm_malloc((name->len+1)*sizeof(char));
180
181         if(sit->name.s==0)
182         {
183                 LM_ERR("out of shm!\n");
184                 shm_free(sit);
185                 return 0;
186         }
187         sit->name.len = name->len;
188         strncpy(sit->name.s, name->s, name->len);
189         sit->name.s[sit->name.len] = '\0';
190
191         if(sh_vars!=0)
192                 sit->n = sh_vars->n + 1;
193         else
194                 sit->n = 1;
195
196 #ifdef GEN_LOCK_T_PREFERED
197         sit->lock = &shvar_locks->locks[sit->n%shvar_locks_no];
198 #else
199         sit->lockidx = sit->n%shvar_locks_no;
200 #endif
201
202         sit->next = sh_vars;
203
204         sh_vars = sit;
205
206         return sit;
207 }
208
209 /* call it with lock set */
210 sh_var_t* set_shvar_value(sh_var_t* shv, int_str *value, int flags)
211 {
212         if(shv==NULL)
213                 return NULL;
214         if(value==NULL)
215         {
216                 if(shv->v.flags&VAR_VAL_STR)
217                 {
218                         shm_free(shv->v.value.s.s);
219                         shv->v.flags &= ~VAR_VAL_STR;
220                 }
221                 memset(&shv->v.value, 0, sizeof(int_str));
222
223                 return shv;
224         }
225
226         if(flags&VAR_VAL_STR)
227         {
228                 if(shv->v.flags&VAR_VAL_STR)
229                 { /* old and new value is str */
230                         if(value->s.len>shv->v.value.s.len)
231                         { /* not enough space to copy */
232                                 shm_free(shv->v.value.s.s);
233                                 memset(&shv->v.value, 0, sizeof(int_str));
234                                 shv->v.value.s.s =
235                                         (char*)shm_malloc((value->s.len+1)*sizeof(char));
236                                 if(shv->v.value.s.s==0)
237                                 {
238                                         LM_ERR("out of shm\n");
239                                         goto error;
240                                 }
241                         }
242                 } else {
243                         memset(&shv->v.value, 0, sizeof(int_str));
244                         shv->v.value.s.s =
245                                         (char*)shm_malloc((value->s.len+1)*sizeof(char));
246                         if(shv->v.value.s.s==0)
247                         {
248                                 LM_ERR("out of shm!\n");
249                                 goto error;
250                         }
251                         shv->v.flags |= VAR_VAL_STR;
252                 }
253                 strncpy(shv->v.value.s.s, value->s.s, value->s.len);
254                 shv->v.value.s.len = value->s.len;
255                 shv->v.value.s.s[value->s.len] = '\0';
256         } else {
257                 if(shv->v.flags&VAR_VAL_STR)
258                 {
259                         shm_free(shv->v.value.s.s);
260                         shv->v.flags &= ~VAR_VAL_STR;
261                         memset(&shv->v.value, 0, sizeof(int_str));
262                 }
263                 shv->v.value.n = value->n;
264         }
265
266         return shv;
267 error:
268         /* set the var to init value */
269         memset(&shv->v.value, 0, sizeof(int_str));
270         shv->v.flags &= ~VAR_VAL_STR;
271         return NULL;
272 }
273
274 sh_var_t* get_shvar_by_name(str *name)
275 {
276         sh_var_t *it;
277
278         if(name==0 || name->s==0 || name->len<=0)
279                 return 0;
280
281         for(it=sh_vars; it; it=it->next)
282         {
283                 if(it->name.len==name->len
284                                 && strncmp(name->s, it->name.s, name->len)==0)
285                         return it;
286         }
287         return 0;
288 }
289
290 void reset_shvars(void)
291 {
292         sh_var_t *it;
293         for(it=sh_vars; it; it=it->next)
294         {
295                 if(it->v.flags&VAR_VAL_STR)
296                 {
297                         shm_free(it->v.value.s.s);
298                         it->v.flags &= ~VAR_VAL_STR;
299                 }
300                 memset(&it->v.value, 0, sizeof(int_str));
301         }
302 }
303
304 void destroy_shvars(void)
305 {
306         sh_var_t *it;
307         sh_var_t *it0;
308
309         it = sh_vars;
310         while(it)
311         {
312                 it0 = it;
313                 it = it->next;
314                 shm_free(it0->name.s);
315                 if(it0->v.flags&VAR_VAL_STR)
316                         shm_free(it0->v.value.s.s);
317                 shm_free(it0);
318         }
319
320         sh_vars = 0;
321 }
322
323
324 /********* PV functions *********/
325 int pv_parse_shvar_name(pv_spec_p sp, str *in)
326 {
327         if(in==NULL || in->s==NULL || sp==NULL)
328                 return -1;
329         
330         sp->pvp.pvn.type = PV_NAME_PVAR;
331         sp->pvp.pvn.u.dname = (void*)add_shvar(in);
332
333         if(sp->pvp.pvn.u.dname==NULL)
334         {
335                 LM_ERR("cannot register shvar [%.*s]\n", in->len, in->s);
336                 return -1;
337         }
338
339         return 0;
340 }
341
342 int pv_get_shvar(struct sip_msg *msg,  pv_param_t *param,
343                 pv_value_t *res)
344 {
345         int len = 0;
346         char *sval = NULL;
347         sh_var_t *shv=NULL;
348         
349         if(msg==NULL || res==NULL)
350                 return -1;
351
352         if(param==NULL || param->pvn.u.dname==0)
353                 return pv_get_null(msg, param, res);
354         
355         shv= (sh_var_t*)param->pvn.u.dname;
356
357         lock_shvar(shv);
358         if(shv->v.flags&VAR_VAL_STR)
359         {
360                 if(shv_cpy.s==NULL || shv_cpy.len < shv->v.value.s.len)
361                 {
362                         if(shv_cpy.s!=NULL)
363                                 pkg_free(shv_cpy.s);
364                         shv_cpy.s = (char*)pkg_malloc(shv->v.value.s.len*sizeof(char));
365                         if(shv_cpy.s==NULL)
366                         {
367                                 unlock_shvar(shv);
368                                 LM_ERR("no more pkg mem\n");
369                                 return pv_get_null(msg, param, res);
370                         }
371                 }
372                 strncpy(shv_cpy.s, shv->v.value.s.s, shv->v.value.s.len);
373                 shv_cpy.len = shv->v.value.s.len;
374                 
375                 unlock_shvar(shv);
376                 
377                 res->rs = shv_cpy;
378                 res->flags = PV_VAL_STR;
379         } else {
380                 res->ri = shv->v.value.n;
381                 
382                 unlock_shvar(shv);
383                 
384                 sval = sint2str(res->ri, &len);
385                 res->rs.s = sval;
386                 res->rs.len = len;
387                 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
388         }
389         return 0;
390 }
391
392 int pv_set_shvar(struct sip_msg* msg, pv_param_t *param,
393                 int op, pv_value_t *val)
394 {
395         int_str isv;
396         int flags;
397
398         if(param==NULL)
399         {
400                 LM_ERR("bad parameters\n");
401                 return -1;
402         }
403
404         if(param->pvn.u.dname==0)
405         {
406                 LM_ERR("error - cannot find shvar\n");
407                 goto error;
408         }
409         lock_shvar((sh_var_t*)param->pvn.u.dname);
410         if(val == NULL)
411         {
412                 isv.n = 0;
413                 set_shvar_value((sh_var_t*)param->pvn.u.dname, &isv, 0);
414                 goto done;
415         }
416         flags = 0;
417         if(val->flags&PV_TYPE_INT)
418         {
419                 isv.n = val->ri;
420         } else {
421                 isv.s = val->rs;
422                 flags |= VAR_VAL_STR;
423         }
424         if(set_shvar_value((sh_var_t*)param->pvn.u.dname, &isv, flags)==NULL)
425         {
426                 LM_ERR("error - cannot set shvar [%.*s] \n",
427                                 ((sh_var_t*)param->pvn.u.dname)->name.len,
428                                 ((sh_var_t*)param->pvn.u.dname)->name.s);
429                 goto error;
430         }
431 done:
432         unlock_shvar((sh_var_t*)param->pvn.u.dname);
433         return 0;
434 error:
435         unlock_shvar((sh_var_t*)param->pvn.u.dname);
436         return -1;
437 }
438
439 struct mi_root* mi_shvar_set(struct mi_root* cmd_tree, void* param)
440 {
441         str sp;
442         str name;
443         int ival;
444         int_str isv;
445         int flags;
446         struct mi_node* node;
447         sh_var_t *shv = NULL;
448
449         node = cmd_tree->node.kids;
450         if(node == NULL)
451                 return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM_S));
452         name = node->value;
453         if(name.len<=0 || name.s==NULL)
454         {
455                 LM_ERR("bad shv name\n");
456                 return init_mi_tree( 500, MI_SSTR("bad shv name"));
457         }
458         shv = get_shvar_by_name(&name);
459         if(shv==NULL)
460                 return init_mi_tree(404, MI_SSTR("Not found"));
461
462         node = node->next;
463         if(node == NULL)
464                 return init_mi_tree(400, MI_SSTR(MI_MISSING_PARM_S));
465         sp = node->value;
466         if(sp.s == NULL)
467                 return init_mi_tree(500, MI_SSTR("type not found"));
468         flags = 0;
469         if(sp.s[0]=='s' || sp.s[0]=='S')
470                 flags = VAR_VAL_STR;
471
472         node= node->next;
473         if(node == NULL)
474                 return init_mi_tree(400, MI_SSTR(MI_MISSING_PARM_S));
475
476         sp = node->value;
477         if(sp.s == NULL)
478         {
479                 return init_mi_tree(500, MI_SSTR("value not found"));
480         }
481         if(flags == 0)
482         {
483                 if(str2sint(&sp, &ival))
484                 {
485                         LM_ERR("bad integer value\n");
486                         return init_mi_tree( 500, MI_SSTR("bad integer value"));
487                 }
488                 isv.n = ival;
489         } else {
490                 isv.s = sp;
491         }
492
493         lock_shvar(shv);
494         if(set_shvar_value(shv, &isv, flags)==NULL)
495         {
496                 unlock_shvar(shv);
497                 LM_ERR("cannot set shv value\n");
498                 return init_mi_tree( 500, MI_SSTR("cannot set shv value"));
499         }
500
501         unlock_shvar(shv);
502         LM_DBG("$shv(%.*s) updated\n", name.len, name.s);
503         return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
504 }
505
506 struct mi_root* mi_shvar_get(struct mi_root* cmd_tree, void* param)
507 {
508         struct mi_root* rpl_tree = NULL;
509         struct mi_node* node;
510         struct mi_attr* attr = NULL;
511         str name;
512         int ival;
513         sh_var_t *shv = NULL;
514
515         node = cmd_tree->node.kids;
516         if(node != NULL)
517         {
518                 name = node->value;
519                 if(name.len<=0 || name.s==NULL)
520                 {
521                         LM_ERR("bad shv name\n");
522                         return init_mi_tree( 500, MI_SSTR("bad shv name"));
523                 }
524                 shv = get_shvar_by_name(&name);
525                 if(shv==NULL)
526                         return init_mi_tree(404, MI_SSTR("Not found"));
527                 
528                 rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
529                 if (rpl_tree==NULL)
530                         return NULL;
531
532                 node = add_mi_node_child(&rpl_tree->node, MI_DUP_VALUE,
533                                 "VAR",3, name.s, name.len);
534                 if(node == NULL)
535                         goto error;
536                 lock_shvar(shv);
537                 if(shv->v.flags&VAR_VAL_STR)
538                 {
539                         attr = add_mi_attr (node, MI_DUP_VALUE, "type", 4, "string", 6);
540                         if(attr == 0)
541                         {
542                                 unlock_shvar(shv);
543                                 goto error;
544                         }
545                         attr = add_mi_attr (node, MI_DUP_VALUE, "value", 5,
546                                         shv->v.value.s.s, shv->v.value.s.len);
547                         if(attr == 0)
548                         {
549                                 unlock_shvar(shv);
550                                 goto error;
551                         }
552                         unlock_shvar(shv);
553                 } else {
554                         ival = shv->v.value.n;
555                         unlock_shvar(shv);
556                         attr = add_mi_attr (node, MI_DUP_VALUE, "type",4, "integer", 7);
557                         if(attr == 0)
558                                 goto error;
559                         name.s = sint2str(ival, &name.len);
560                         attr = add_mi_attr (node, MI_DUP_VALUE, "value",5,
561                                         name.s, name.len);
562                         if(attr == 0)
563                                 goto error;
564                 }
565
566                 goto done;
567         }
568
569         rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
570         if (rpl_tree==NULL)
571                 return NULL;
572
573         for(shv=sh_vars; shv; shv=shv->next)
574         {
575                 node = add_mi_node_child(&rpl_tree->node, MI_DUP_VALUE,
576                                 "VAR", 3, shv->name.s, shv->name.len);
577                 if(node == NULL)
578                         goto error;
579
580                 lock_shvar(shv);
581                 if(shv->v.flags&VAR_VAL_STR)
582                 {
583                         attr = add_mi_attr (node, MI_DUP_VALUE, "type", 4, "string", 6);
584                         if(attr == 0)
585                         {
586                                 unlock_shvar(shv);
587                                 goto error;
588                         }
589                         attr = add_mi_attr (node, MI_DUP_VALUE, "value", 5,
590                                         shv->v.value.s.s, shv->v.value.s.len);
591                         if(attr == 0)
592                         {
593                                 unlock_shvar(shv);
594                                 goto error;
595                         }
596                         unlock_shvar(shv);
597                 } else {
598                         ival = shv->v.value.n;
599                         unlock_shvar(shv);
600                         attr = add_mi_attr (node, MI_DUP_VALUE, "type",4, "integer", 7);
601                         if(attr == 0)
602                                 goto error;
603                         name.s = sint2str(ival, &name.len);
604                         attr = add_mi_attr (node, MI_DUP_VALUE, "value",5,
605                                         name.s, name.len);
606                         if(attr == 0)
607                                 goto error;
608                 }
609         }
610
611 done:
612         return rpl_tree;
613 error:
614         if(rpl_tree!=NULL)
615                 free_mi_tree(rpl_tree);
616         return NULL;
617 }
618
619
620 void rpc_shv_get(rpc_t* rpc, void* c)
621 {
622         str varname;
623         int allvars = 0;
624         sh_var_t *shv = NULL;
625         void* th;
626         void* ih;
627         void* vh;
628
629         if (rpc->scan(c, "S", &varname) != 1) {
630                 allvars = 1;
631         }
632
633         if (!allvars) {
634                 /* Get one variable value */
635                 shv = get_shvar_by_name(&varname);
636                 if(shv==NULL) {
637                         rpc->fault(c, 404, "Variable not found");
638                         return;
639                 }
640                 if (rpc->add(c, "{",  &ih) < 0)
641                 {
642                         rpc->fault(c, 500, "Internal error creating rpc");
643                         return;
644                 }
645                 
646                 lock_shvar(shv);
647                 if(shv->v.flags&VAR_VAL_STR)
648                 {
649                         if(rpc->struct_add(ih, "sss", "name", varname.s, "type", "string", "value", shv->v.value.s.s) < 0)
650                         {
651                                 rpc->fault(c, 500, "Internal error creating rpc data (str)");
652                                 unlock_shvar(shv);
653                                 return;
654                         }
655                 } else {
656                         if(rpc->struct_add(ih, "ssd", "name", varname.s, "type", "int", "value", shv->v.value.n) < 0)
657                         {
658                                 rpc->fault(c, 500, "Internal error creating rpc data (int)");
659                                 unlock_shvar(shv);
660                                 return;
661                         }
662                 }
663                 unlock_shvar(shv);
664
665                 return;
666         }
667         if (rpc->add(c, "{", &th) < 0)
668         {
669                 rpc->fault(c, 500, "Internal error creating rpc");
670                 return;
671         }
672
673         if(rpc->struct_add(th, "{", "items", &ih) < 0)
674                {
675                          rpc->fault(c, 500, "Internal error creating rpc th");
676                          return;
677                }
678
679         for(shv=sh_vars; shv; shv=shv->next)
680         {
681                 lock_shvar(shv);
682                 if(rpc->struct_add(ih, "{", "shv", &vh) < 0)
683                {
684                          rpc->fault(c, 500, "Internal error creating rpc th");
685                          return;
686                }
687                 if(shv->v.flags&VAR_VAL_STR)
688                 {
689                         if(rpc->struct_add(vh, "sss", "name", shv->name.s, "type", "string", "value", shv->v.value.s.s) < 0)
690                         {
691                                 rpc->fault(c, 500, "Internal error creating rpc data");
692                                 unlock_shvar(shv);
693                                 return;
694                         }
695                 } else {
696                         if(rpc->struct_add(vh, "ssd", "name", shv->name.s, "type", "int", "value", shv->v.value.n) < 0)
697                         {
698                                 rpc->fault(c, 500, "Internal error creating rpc data");
699                                 unlock_shvar(shv);
700                                 return;
701                         }
702                 }
703                 unlock_shvar(shv);
704         }
705
706         return ;
707 }
708
709 void rpc_shv_set(rpc_t* rpc, void* c)
710 {
711         str varname, type, value;
712         int ival = 0;
713         int_str isv;
714         sh_var_t *shv = NULL;
715         int flags = 0;
716         LM_DBG("Entering SHV_set\n");
717
718         if (rpc->scan(c, "S", &varname) != 1) {
719                 rpc->fault(c, 500, "Missing parameter varname (Parameters: varname type value)");
720                 return;
721         }
722         LM_DBG("SHV_set Varname %.*s \n", varname.len, varname.s);
723         if (rpc->scan(c, "S", &type) != 1) {
724                 rpc->fault(c, 500, "Missing parameter type (Parameters: varname type value)");
725                 return;
726         }
727         if (strcasecmp(type.s, "int") == 0 ) {
728                 if (rpc->scan(c, "d", &ival) != 1) {
729                         rpc->fault(c, 500, "Missing integer parameter value (Parameters: varname type value)");
730                         return;
731                 }
732                 isv.n = ival;
733         } else  if (strcasecmp(type.s, "str") == 0 ) {
734                 /* String value */
735                 if (rpc->scan(c, "S", &value) != 1) {
736                         rpc->fault(c, 500, "Missing parameter value (Parameters: varname type value)");
737                         return;
738                 }
739                 isv.s = value;
740                 flags = VAR_VAL_STR;
741         } else {
742                 rpc->fault(c, 500, "Unknown parameter type (Types: int or str)");
743                 return;
744         }
745
746         shv = get_shvar_by_name(&varname);
747         if(shv==NULL) {
748                 rpc->fault(c, 404, "Variable not found");
749                 return;
750         }
751                 
752         lock_shvar(shv);
753         if(set_shvar_value(shv, &isv, flags)==NULL)
754         {
755                 rpc->fault(c, 500, "Cannot set shared variable value");
756                 LM_ERR("cannot set shv value\n");
757         } else {
758                 rpc->printf(c, "Ok. Variable set to new value.");
759         }
760
761         unlock_shvar(shv);
762         return;
763 }
764
765 int param_set_xvar( modparam_t type, void* val, int mode)
766 {
767         str s;
768         char *p;
769         int_str isv;
770         int flags;
771         int ival;
772         script_var_t *pkv;
773         sh_var_t *shv;
774
775         if(!shm_initialized()!=0)
776         {
777                 LM_ERR("shm not initialized - cannot set value for PVs\n");
778                 return -1;
779         }
780
781         s.s = (char*)val;
782         if(s.s == NULL || s.s[0] == '\0')
783                 goto error;
784
785         p = s.s;
786         while(*p && *p!='=') p++;
787
788         if(*p!='=')
789                 goto error;
790         
791         s.len = p - s.s;
792         if(s.len == 0)
793                 goto error;
794         p++;
795         flags = 0;
796         if(*p!='s' && *p!='S' && *p!='i' && *p!='I')
797                 goto error;
798
799         if(*p=='s' || *p=='S')
800                 flags = VAR_VAL_STR;
801         p++;
802         if(*p!=':')
803                 goto error;
804         p++;
805         isv.s.s = p;
806         isv.s.len = strlen(p);
807         if(flags != VAR_VAL_STR) {
808                 if(str2sint(&isv.s, &ival)<0)
809                         goto error;
810                 isv.n = ival;
811         }
812         if(mode==0) {
813                 pkv = add_var(&s);
814                 if(pkv==NULL)
815                         goto error;
816                 if(set_var_value(pkv, &isv, flags)==NULL)
817                         goto error;
818         } else {
819                 shv = add_shvar(&s);
820                 if(shv==NULL)
821                         goto error;
822                 if(set_shvar_value(shv, &isv, flags)==NULL)
823                         goto error;
824         }
825         
826         return 0;
827 error:
828         LM_ERR("unable to set shv parame [%s]\n", s.s);
829         return -1;
830 }
831
832 int param_set_var( modparam_t type, void* val)
833 {
834         return param_set_xvar(type, val, 0);
835 }
836
837 int param_set_shvar( modparam_t type, void* val)
838 {
839         return param_set_xvar(type, val, 1);
840 }
841
842 /* vi: set ts=4 sw=4 tw=79:ai:cindent: */