eval.c

00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2006 iptelorg GmbH
00005  *
00006  * This file is part of ser, a free SIP server.
00007  *
00008  * ser is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * For a license to use the ser software under conditions
00014  * other than those described here, or to purchase support for this
00015  * software, please contact iptel.org by e-mail at the following addresses:
00016  *    info@iptel.org
00017  *
00018  * ser is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software
00025  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  */
00027 
00028 
00029 #include <string.h>
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032 #include <ctype.h>
00033 #include "../../route.h"
00034 #include "../../sr_module.h"
00035 #include "../../mem/mem.h"
00036 #include "../../str.h"
00037 #include "../../error.h"
00038 #include "../../config.h"
00039 #include "../../trim.h"
00040 #include "../../select.h"
00041 #include "../../ut.h"
00042 #include "../xlog/xl_lib.h"
00043 #include "../../select_buf.h"
00044 
00045 #include "../../globals.h"
00046 #include "../../route.h"
00047 #include "../../parser/msg_parser.h"
00048 #include "../../action.h"
00049 #include "../../script_cb.h"
00050 #include "../../dset.h"
00051 #include "../../usr_avp.h"
00052 
00053 MODULE_VERSION
00054 
00055 #define MODULE_NAME "eval"
00056 
00057 enum {evtVoid=0, evtInt, evtStr};
00058 
00059 struct eval_str {
00060         str s;
00061         int cnt;
00062 };
00063 
00064 struct eval_value {
00065         union {
00066                 long n;
00067                 struct eval_str *s;
00068         } u;
00069         int type;
00070 };
00071 
00072 struct register_item {
00073         char *name;
00074         struct eval_value value;
00075         struct register_item *next;
00076 };
00077 
00078 struct stack_item {
00079         struct eval_value value;
00080         struct stack_item *prev;
00081         struct stack_item *next;
00082 };
00083 
00084 static int stack_no = 0;
00085 static struct stack_item *stack_head = 0;
00086 static struct stack_item *stack_tail = 0;
00087 
00088 static struct register_item* registers = 0;
00089 
00090 
00091 #define destroy_value(val) { \
00092         if ((val).type == evtStr && (val).u.s && (val).u.s->cnt > 0) { \
00093                 (val).u.s->cnt--; \
00094                 if ((val).u.s->cnt == 0) \
00095                         pkg_free((val).u.s); \
00096         } \
00097         (val).type = evtVoid; \
00098 }
00099 
00100 #define assign_value(dest, src) { \
00101         if (&(dest) != &(src)) { \
00102                 destroy_value(dest); \
00103                 dest = src; \
00104                 if ((dest).type == evtStr && (dest).u.s && (dest).u.s->cnt > 0) \
00105                         (dest).u.s->cnt++; \
00106         } \
00107 }
00108 
00109 static int get_as_int(struct eval_value *value, long* val) {
00110         switch (value->type) {
00111                 case evtInt:
00112                         *val = value->u.n;
00113                         return 1;
00114                 case evtStr:
00115                         if (value->u.s->s.s && value->u.s->s.len && value->u.s->s.len <= 25) {
00116                                 char *err;
00117                                 char buf[25+1];
00118                                 memcpy(buf, value->u.s->s.s, value->u.s->s.len);
00119                                 buf[value->u.s->s.len] = '\0';
00120                                 *val = strtol(buf, &err, 10);
00121                                 if (*err == 0)
00122                                         return 1;
00123                         }
00124                         ERR(MODULE_NAME": cannot convert '%.*s' as int\n", value->u.s->s.len, value->u.s->s.s);
00125                         return -1;
00126                 default:
00127                         BUG("Bad value type %d\n", value->type);
00128                         return -1;
00129         }
00130 }
00131 
00132 static void get_as_str(struct eval_value *value, str *s) {
00133         static char buf[25];
00134         switch (value->type) {
00135                 case evtInt:
00136                         s->len = snprintf(buf, sizeof(buf)-1, "%ld", value->u.n);
00137                         s->s = buf;
00138                         break;
00139                 case evtStr:
00140                         *s = value->u.s->s;
00141                         break;
00142                 default:
00143                         s->s = 0;
00144                         s->len = 0;
00145                         break;
00146         }
00147 }
00148 
00149 static int get_as_bool(struct eval_value *value) {
00150         switch (value->type) {
00151                 case evtVoid:
00152                         return 0;
00153                 case evtInt:
00154                         return value->u.n != 0;
00155                 case evtStr:
00156                         return (value->u.s->s.s && value->u.s->s.len > 0);
00157                 default:
00158                         BUG("Bad value type %d\n", value->type);
00159                         return -1;
00160         }
00161 }
00162 
00163 static struct eval_str* eval_str_malloc(str* s) {
00164         struct eval_str* p;
00165         p = pkg_malloc(sizeof(*p)+s->len);
00166         if (p) {
00167                 p->s.s = (char*)p+sizeof(*p);
00168                 if (s->len && s->s != 0)
00169                         memcpy(p->s.s, s->s, s->len);
00170                 if (s->s == 0 && s->len)
00171                         s->s = p->s.s;
00172                 p->s.len = s->len;
00173                 p->cnt = 1;
00174         }
00175         return p;
00176 }
00177 
00178 /* taken from modules/textops */
00179 #define is_space(_p) ((_p) == '\t' || (_p) == '\n' || (_p) == '\r' || (_p) == ' ')
00180 
00181 static void get_uri_and_skip_until_params(str *param_area, str *uri) {
00182         int i, quoted, uri_pos, uri_done;
00183 
00184         uri->len = 0;
00185         uri->s = 0;
00186         uri_done = 0;
00187         for (i=0; i<param_area->len && param_area->s[i]!=';'; ) {       /* [ *(token LSW)/quoted-string ] "<" addr-spec ">" | addr-spec */
00188                 /* skip name */
00189 
00190                 for (quoted=0, uri_pos=i; i<param_area->len; i++) {
00191                         if (!quoted) {
00192                                 if (param_area->s[i] == '\"') {
00193                                         quoted = 1;
00194                                         uri_pos = -1;
00195                                 }
00196                                 else if (param_area->s[i] == '<' || param_area->s[i] == ';' || is_space(param_area->s[i])) break;
00197                         }
00198                         else if (param_area->s[i] == '\"' && param_area->s[i-1] != '\\') quoted = 0;
00199                 }
00200                 if (uri_pos >= 0 && !uri_done) {
00201                         uri->s = param_area->s+uri_pos;
00202                         uri->len = param_area->s+i-uri->s;
00203                 }
00204                 /* skip uri */
00205                 while (i<param_area->len && is_space(param_area->s[i])) i++;
00206                 if (i<param_area->len && param_area->s[i]=='<') {
00207                         uri->s = param_area->s+i;
00208                         uri->len = 0;
00209                         for (quoted=0; i<param_area->len; i++) {
00210                                 if (!quoted) {
00211                                         if (param_area->s[i] == '\"') quoted = 1;
00212                                         else if (param_area->s[i] == '>') {
00213                                                 uri->len = param_area->s+i-uri->s+1;
00214                                                 uri_done = 1;
00215                                                 break;
00216                                         }
00217                                 }
00218                                 else if (param_area->s[i] == '\"' && param_area->s[i-1] != '\\') quoted = 0;
00219                         }
00220                 }
00221         }
00222         param_area->s+= i;
00223         param_area->len-= i;
00224 }
00225 
00226 static int find_next_value(char** start, char* end, str* val, str* lump_val) {
00227         int quoted = 0;
00228         lump_val->s = *start;
00229         while (*start < end && is_space(**start) ) (*start)++;
00230         val->s = *start;
00231         while ( *start < end && (**start != ',' || quoted) ) {
00232                 if (**start == '\"' && (!quoted || (*start)[-1]!='\\') )
00233                         quoted = ~quoted;
00234                 (*start)++;
00235         }
00236         val->len = *start - val->s;
00237         while (val->len > 0 && is_space(val->s[val->len-1])) val->len--;
00238 /* we cannot automatically strip quotes!!! an example why: "name" <sip:ssss>;param="bar"
00239         if (val->len >= 2 && val->s[0] == '\"' && val->s[val->len-1] == '\"') {
00240                 val->s++;
00241                 val->len -= 2;
00242         }
00243 */
00244         while (*start < end && **start != ',') (*start)++;
00245         if (*start < end) {
00246                 (*start)++;
00247         }
00248         lump_val->len = *start - lump_val->s;
00249         return (*start < end);
00250 }
00251 
00252 #define MAX_HF_VALUES 30
00253 
00254 static int parse_hf_values(str s, int* n, str** vals) {
00255         static str values[MAX_HF_VALUES];
00256         char *start, *end;
00257         str lump_val;
00258         *n = 0;
00259         *vals = values;
00260         if (!s.s) return 1;
00261         start = s.s;
00262         end = start+s.len;
00263         while (start < end) {
00264                 find_next_value(&start, end, &values[*n], &lump_val);
00265                 if (*n >= MAX_HF_VALUES) {
00266                         ERR(MODULE_NAME": too many values\n");
00267                         return -1;
00268                 }
00269                 (*n)++;
00270         }
00271         return 1;
00272 }
00273 
00274 static void destroy_stack() {
00275         struct stack_item *p;
00276         while (stack_head) {
00277                 destroy_value(stack_head->value);
00278                 p = stack_head;
00279                 stack_head = stack_head->next;
00280                 pkg_free(p);
00281         }
00282         stack_tail = stack_head;
00283         stack_no = 0;
00284 }
00285 
00286 static void destroy_register_values() {
00287         struct register_item *p;
00288         for (p=registers; p; p=p->next) {
00289                 destroy_value(p->value);
00290         }
00291 }
00292 
00293 static void remove_stack_item(struct stack_item *s) {
00294         if (s->prev)
00295                 s->prev->next = s->next;
00296         else
00297                 stack_head = s->next;
00298         if (s->next)
00299                 s->next->prev = s->prev;
00300         else
00301                 stack_tail = s->prev;
00302         destroy_value(s->value);
00303         pkg_free(s);
00304         stack_no--;
00305 }
00306 
00307 static void insert_stack_item(struct stack_item *s, struct stack_item *pivot, int behind) {
00308         if (stack_head == NULL) {
00309                 s->prev = s->next = 0;
00310         }
00311         else if (behind) {
00312                 if (pivot) {
00313                         s->next = pivot->next;
00314                         s->prev = pivot;
00315                 }
00316                 else {
00317                         s->next = 0;
00318                         s->prev = stack_tail;  /* bottom (tail) */
00319                 }
00320         }
00321         else {
00322                 if (pivot) {
00323                         s->prev = pivot->prev;
00324                         s->next = pivot;
00325                 }
00326                 else {
00327                         s->next = stack_head;  /* top (head) */
00328                         s->prev = 0;
00329                 }
00330         }
00331         if (!s->prev)
00332                 stack_head = s;
00333         else
00334                 s->prev->next = s;
00335         if (!s->next)
00336                 stack_tail = s;
00337         else
00338                 s->next->prev = s;
00339         stack_no++;
00340 }
00341 
00342 static int declare_register(modparam_t type, char* param) {
00343         struct register_item **p;
00344         char *c;
00345         for (c=param; *c; c++) {
00346                 if (    (*c >= 'a' && *c <= 'z') ||
00347                         (*c >= 'A' && *c <= 'Z') ||
00348                         (*c >= '0' && *c <= '9') ||
00349                         (*c == '_') ) {
00350                         ;
00351                 } else {
00352                         ERR(MODULE_NAME": illegal register name\n");
00353                         return E_CFG;
00354                 }
00355         }
00356         for (p = &registers; *p!= 0; p = &(*p)->next);
00357         *p = pkg_malloc(sizeof(**p));
00358         if (!*p) return E_OUT_OF_MEM;
00359 
00360         memset(*p, 0, sizeof(**p));
00361         (*p)->name = param;
00362         return 0;
00363 }
00364 
00365 static int mod_pre_script_cb(struct sip_msg *msg, unsigned int flags, void *param) {
00366         destroy_stack();
00367         destroy_register_values();
00368         return 1;
00369 }
00370 
00371 static struct register_item* find_register(char* s, int len) {
00372         struct register_item *p;
00373         for (p=registers; p; p=p->next) {
00374                 if (strlen(p->name) == len && strncasecmp(p->name, s, len) == 0)
00375                         break;
00376         }
00377         return p;
00378 }
00379 
00380 static struct stack_item* find_stack_item(int n) {
00381         struct stack_item *p;
00382         if ((n >= 0 && n >= stack_no) || (n<0 && -n > stack_no)) {
00383                 return NULL;
00384         }
00385         p = NULL;
00386         if (n >= 0) {
00387                 for (p = stack_head; p && n>0; p=p->next, n--);
00388         }
00389         else {
00390                 for (p = stack_tail, n=-n-1; p && n>0; p=p->prev, n--);
00391         }
00392         return p;
00393 }
00394 
00395 /* module exported functions */
00396 static void print_eval_value(struct eval_value* v) {
00397         switch (v->type) {
00398                 case evtStr:
00399                         if (v->u.s)
00400                                 fprintf(stderr, "s:'%.*s', cnt:%d\n", v->u.s->s.len, v->u.s->s.s, v->u.s->cnt);
00401                         else
00402                                 fprintf(stderr, "s:<null>\n");
00403                         break;
00404                 case evtInt:
00405                         fprintf(stderr, "i:%ld\n", v->u.n);
00406                         break;
00407                 default:;
00408                         fprintf(stderr, "type:%d\n", v->type);
00409                         break;
00410         }
00411 }
00412 
00413 static int eval_dump_func(struct sip_msg *msg, char *param1, char *param2) {
00414         struct stack_item *si;
00415         struct register_item *ri;
00416         int i;
00417         fprintf(stderr, "Stack (no=%d):\n", stack_no);
00418         for (si=stack_head, i=0; si; si=si->next, i++) {
00419                 fprintf(stderr, "# %.2d ", i);
00420                 print_eval_value(&si->value);
00421         }
00422         for (si=stack_tail, i=-1; si; si=si->prev, i--) {
00423                 fprintf(stderr, "#%.2d ", i);
00424                 print_eval_value(&si->value);
00425         }
00426         fprintf(stderr, "Registers:\n");
00427         for (ri=registers; ri; ri=ri->next) {
00428                 fprintf(stderr, "%s: ", ri->name);
00429                 print_eval_value(&ri->value);
00430         }
00431         return 1;
00432 }
00433 
00434 
00435 static int xlbuf_size = 4096;
00436 static xl_print_log_f* xl_print = NULL;
00437 static xl_parse_format_f* xl_parse = NULL;
00438 #define NO_SCRIPT -1
00439 
00440 
00441 enum {esotAdd, esotInsert, esotXchg, esotPut, esotGet, esotPop, esotAddValue, esotInsertValue};
00442 enum {esovtInt, esovtStr, esovtAvp, esovtXStr, esovtRegister, esovtFunc, esovtSelect};
00443 enum {esofNone=0, esofTime, esofUuid, esofStackNo};
00444 
00445 struct eval_location_func {
00446         int type;
00447         char *name;
00448 };
00449 
00450 static struct eval_location_func loc_functions[] = {
00451         {esofTime, "time"},
00452         {esofUuid, "uuid"},
00453         {esofStackNo, "stackno"},
00454 
00455         {esofNone, NULL}
00456 };
00457 
00458 struct eval_location {
00459         int value_type;
00460         union {
00461                 int n;
00462                 struct eval_str s;
00463                 xl_elog_t* xl;
00464                 struct register_item *reg;
00465                 avp_ident_t avp;
00466                 select_t* select;
00467                 struct eval_location_func *func;
00468         } u;
00469 };
00470 
00471 struct eval_stack_oper {
00472         int oper_type;
00473         struct eval_location loc;
00474 };
00475 
00476 static int parse_location(str s, struct eval_location *p) {
00477         if (s.len >= 2 && s.s[1] == ':') {
00478                 switch (s.s[0]) {
00479                         case 'r':
00480                                 p->u.reg = find_register(s.s+2, s.len-2);
00481                                 if (!p->u.reg) {
00482                                         ERR(MODULE_NAME": register '%.*s' not found\n", s.len-2, s.s+2);
00483                                         return E_CFG;
00484                                 }
00485                                 p->value_type = esovtRegister;
00486                                 break;
00487                         case 'x':
00488                                 if (!xl_print) {
00489                                         xl_print=(xl_print_log_f*)find_export("xprint", NO_SCRIPT, 0);
00490                                         if (!xl_print) {
00491                                                 ERR(MODULE_NAME": cannot find \"xprint\", is module xlog loaded?\n");
00492                                                 return E_UNSPEC;
00493                                         }
00494                                 }
00495 
00496                                 if (!xl_parse) {
00497                                         xl_parse=(xl_parse_format_f*)find_export("xparse", NO_SCRIPT, 0);
00498 
00499                                         if (!xl_parse) {
00500                                                 ERR(MODULE_NAME": cannot find \"xparse\", is module xlog loaded?\n");
00501                                                 return E_UNSPEC;
00502                                         }
00503                                 }
00504 
00505                                 if(xl_parse(s.s+2, &p->u.xl) < 0) {
00506                                         ERR(MODULE_NAME": wrong xl_lib format '%s'\n", s.s+2);
00507                                         return E_UNSPEC;
00508                                 }
00509                                 p->value_type = esovtXStr;
00510                                 break;
00511                         case 'f': {
00512                                 struct eval_location_func* f;
00513                                 s.s += 2;
00514                                 s.len -= 2;
00515                                 for (f=loc_functions; f->type != esofNone; f++) {
00516                                         if (strlen(f->name)==s.len && strncasecmp(s.s, f->name, s.len) == 0) {
00517                                                 p->value_type = esovtFunc;
00518                                                 p->u.func = f;
00519                                                 break;
00520                                         }
00521                                 }
00522                                 if (!f) {
00523                                         ERR(MODULE_NAME": unknown function '%.*s'\n", s.len, s.s);
00524                                         return E_CFG;
00525                                 }
00526                                 break;
00527                         }
00528                         case 's':
00529                                 s.s += 2;
00530                                 s.len -= 2;
00531                                 /* no break */
00532                         default:
00533                                 p->u.s.s = s;
00534                                 p->u.s.cnt = 0;
00535                                 p->value_type = esovtStr;
00536                                 break;
00537                 }
00538         }
00539         else {
00540                 char *err;
00541                 if (s.len > 1 && s.s[0]=='$') {
00542                         s.s++;
00543                         s.len--;
00544                         if (parse_avp_ident(&s, &p->u.avp) == 0) {
00545                                 if (p->u.avp.flags & AVP_NAME_RE) {
00546                                         ERR(MODULE_NAME": avp regex not allowed\n");
00547                                         return E_CFG;
00548                                 }
00549                                 p->value_type = esovtAvp;
00550                                 return 1;
00551                         }
00552                         s.s--;
00553                         s.len++;
00554                 }
00555                 else if (s.len > 1 && s.s[0]=='@') {
00556                         if (parse_select(&s.s, &p->u.select) >= 0) {
00557                                 p->value_type = esovtSelect;
00558                                 return 1;
00559                         }
00560                 }
00561                 p->u.n = strtol(s.s, &err, 10);
00562                 if (*err) {
00563                         p->u.s.s = s;
00564                         p->u.s.cnt = 0;
00565                         p->value_type = esovtStr;
00566                 }
00567                 else {
00568                         p->value_type = esovtInt;
00569                 }
00570         }
00571         return 1;
00572 }
00573 
00574 static int eval_xl(struct sip_msg *msg, xl_elog_t* xl, str* s) {
00575         static char *xlbuf=NULL;
00576         int xllen = 0;
00577 
00578         if (!xlbuf) {
00579                 xlbuf = (char*) pkg_malloc((xlbuf_size+1)*sizeof(char));
00580                 if (!xlbuf) {
00581                         ERR(MODULE_NAME": eval_xl: No memory left for format buffer\n");
00582                         return E_OUT_OF_MEM;
00583                 }
00584         }
00585         xllen = xlbuf_size;
00586         if (xl_print(msg, xl, xlbuf, &xllen) < 0) {
00587                 ERR(MODULE_NAME": eval_xl: Error while formatting result\n");
00588                 return E_UNSPEC;
00589         }
00590         s->s = xlbuf;
00591         s->len = xllen;
00592         return 1;
00593 }
00594 
00595 SELECT_F(select_sys_unique)
00596 
00597 static int eval_location(struct sip_msg *msg, struct eval_location* so, struct eval_value* v, int get_static_str) {
00598         static struct eval_str ss;
00599 
00600         v->type = evtVoid;
00601         switch (so->value_type) {
00602                 case esovtInt:
00603                         v->type = evtInt;
00604                         v->u.n = so->u.n;
00605                         break;
00606                 case esovtStr:
00607                         v->type = evtStr;
00608                         v->u.s = &so->u.s;
00609                         break;
00610                 case esovtXStr: {
00611                         str s;
00612                         int ret;
00613                         ret = eval_xl(msg, so->u.xl, &s);
00614                         if (ret < 0) return ret;
00615                         if (get_static_str) {
00616                                 ss.s = s;
00617                                 ss.cnt = 0;
00618                                 v->u.s = &ss;
00619                         }
00620                         else {
00621                                 v->u.s = eval_str_malloc(&s);
00622                                 if (!v->u.s) {
00623                                         ERR(MODULE_NAME": out of memory to allocate xl string\n");
00624                                         return E_OUT_OF_MEM;
00625                                 }
00626                         }
00627                         v->type = evtStr;
00628                         break;
00629                 }
00630                 case esovtRegister:
00631                         if (get_static_str)
00632                                 *v = so->u.reg->value;  /* do not incement cnt */
00633                         else
00634                                 assign_value(*v, so->u.reg->value);
00635                         break;
00636                 case esovtAvp: {
00637                         avp_t* avp;
00638                         avp_value_t val;
00639 
00640                         if (so->u.avp.flags & AVP_INDEX_ALL)
00641                                 avp = search_first_avp(so->u.avp.flags & ~AVP_INDEX_ALL, so->u.avp.name, &val, NULL);
00642                         else
00643                                 avp = search_avp_by_index(so->u.avp.flags, so->u.avp.name, &val, so->u.avp.index);
00644                         if (!avp) {
00645                                 ERR(MODULE_NAME": avp '%.*s'[%d] not found\n", so->u.avp.name.s.len, so->u.avp.name.s.s, so->u.avp.index);
00646                                 return -1;
00647                         }
00648                         if (avp->flags & AVP_VAL_STR) {
00649                                 if (get_static_str) {
00650                                         ss.s = val.s;
00651                                         ss.cnt = 0;
00652                                         v->u.s = &ss;
00653                                 }
00654                                 else {
00655                                         v->u.s = eval_str_malloc(&val.s);
00656                                         if (!v->u.s) {
00657                                                 ERR(MODULE_NAME": out of memory to allocate avp string\n");
00658                                                 return E_OUT_OF_MEM;
00659                                         }
00660                                 }
00661                                 v->type = evtStr;
00662                         }
00663                         else {
00664                                 v->type = evtInt;
00665                                 v->u.n = val.n;
00666                         }
00667                         break;
00668                 }
00669                 case esovtSelect: {
00670                         str s;
00671                         int ret = run_select(&s, so->u.select, msg);
00672                         if (ret < 0 || ret > 0) return -1;
00673                         if (get_static_str) {
00674                                 ss.s = s;
00675                                 ss.cnt = 0;
00676                                 v->u.s = &ss;
00677                         }
00678                         else {
00679                                 v->u.s = eval_str_malloc(&s);
00680                                 if (!v->u.s) {
00681                                         ERR(MODULE_NAME": out of memory to allocate select string\n");
00682                                         return E_OUT_OF_MEM;
00683                                 }
00684                         }
00685                         v->type = evtStr;
00686                         break;
00687                 }
00688                 case esovtFunc: {
00689                         switch (so->u.func->type) {
00690                                 case esofTime: {
00691                                         time_t stamp;
00692                                         stamp = time(NULL);
00693                                         v->type = evtInt;
00694                                         v->u.n = stamp;
00695                                         break;
00696                                 }
00697                                 case esofUuid: {
00698                                         str s;
00699                                         select_sys_unique(&s, 0, msg);
00700                                         if (get_static_str) {
00701                                                 ss.s = s;
00702                                                 ss.cnt = 0;
00703                                                 v->u.s = &ss;
00704                                         }
00705                                         else {
00706                                                 v->u.s = eval_str_malloc(&s);
00707                                                 if (!v->u.s) {
00708                                                         ERR(MODULE_NAME": out of memory to allocate uuid string\n");
00709                                                         return E_OUT_OF_MEM;
00710                                                 }
00711                                         }
00712                                         v->type = evtStr;
00713                                         break;
00714                                 }
00715                                 case esofStackNo:
00716                                         v->type = evtInt;
00717                                         v->u.n = stack_no;
00718                                         break;
00719                                 default:
00720                                         BUG("bad func type (%d)\n", so->u.func->type);
00721                                         return -1;
00722                         }
00723                         break;
00724                 }
00725                 default:
00726                         BUG("Bad value type (%d)\n", so->value_type);
00727                         return -1;
00728         }
00729         return 1;
00730 }
00731 
00732 static int fixup_location_12( void** param, int param_no) {
00733         struct eval_location *so;
00734         str s;
00735         s.s = *param;
00736         s.len = strlen(s.s);
00737         so = pkg_malloc(sizeof(*so));
00738         if (!so) return E_OUT_OF_MEM;
00739         if (parse_location(s, so) < 0) {
00740                 ERR(MODULE_NAME": parse location error '%s'\n", s.s);
00741                 return E_CFG;
00742         }
00743         *param = so;
00744         return 0;
00745 }
00746 
00747 static int fixup_stack_oper(void **param, int param_no, int oper_type) {
00748         str s;
00749         struct eval_stack_oper *p;
00750         int ret;
00751 
00752         if (param_no == 2) {
00753                 return fixup_location_12(param, param_no);
00754         }
00755         p = pkg_malloc(sizeof(*p));
00756         if (!p) return E_OUT_OF_MEM;
00757         p->oper_type = oper_type;
00758         s.s = *param;
00759         s.len = strlen(s.s);
00760         *param = p;
00761         ret = parse_location(s, &p->loc);
00762         if (ret < 0) return ret;
00763 
00764         switch (p->oper_type) {
00765                 case esotXchg:
00766                         if (p->loc.value_type == esovtAvp || p->loc.value_type == esovtSelect) {
00767                                 ERR(MODULE_NAME": avp non supported for xchg\n");
00768                                 return E_CFG;
00769                         }
00770                         /* no break */
00771                 case esotPop:
00772                 case esotGet:
00773                         if (p->loc.value_type != esovtRegister && p->loc.value_type != esovtAvp) {
00774                                 ERR(MODULE_NAME": non supported read only location\n");
00775                                 return E_CFG;
00776                         }
00777                         break;
00778                 default:;
00779         }
00780         return 0;
00781 }
00782 
00783 static int eval_stack_oper_func(struct sip_msg *msg, char *param1, char *param2) {
00784         int ret, idx;
00785         struct stack_item *pivot;
00786         struct eval_stack_oper *so;
00787         struct run_act_ctx ra_ctx;
00788 
00789         so = (struct eval_stack_oper *)param1;
00790         if (param2) {
00791                 long l;
00792                 struct eval_value v;
00793                 eval_location(msg, (struct eval_location*) param2, &v, 1);
00794                 ret = get_as_int(&v, &l);
00795                 if (ret < 0) return ret;
00796                 idx = l;
00797         }
00798         else {
00799                 switch (so->oper_type) {  /* default values */
00800                         case esotAdd:
00801                         case esotAddValue:
00802                                 idx = -1;
00803                                 break;
00804                         default:
00805                                 idx = 0;
00806                                 break;
00807                 }
00808         }
00809 
00810         pivot = find_stack_item(idx);
00811         if ( !(pivot!=NULL || ((so->oper_type == esotAdd || so->oper_type == esotAddValue) && idx == -1) || ((so->oper_type == esotInsert || so->oper_type == esotInsertValue) && idx == 0)) )
00812                 return -1;
00813 
00814         switch (so->oper_type) {
00815                 case esotGet:
00816                 case esotPop:
00817                         switch (so->loc.value_type) {
00818                                 case esovtRegister:
00819                                         assign_value(so->loc.u.reg->value, pivot->value);
00820                                         if (so->oper_type == esotPop)
00821                                                 remove_stack_item(pivot);
00822                                         return 1;
00823                                 case esovtAvp: {
00824                                         struct action a;
00825                                         avp_spec_t attr;
00826 
00827                                         a.type = ASSIGN_T;
00828                                         a.count = 2;
00829                                         a.val[0].type = AVP_ST;
00830                                         attr.type = so->loc.u.avp.flags;
00831                                         attr.name = so->loc.u.avp.name;
00832                                         attr.index = so->loc.u.avp.index;
00833                                         a.val[0].u.attr = &attr;
00834                                         switch (pivot->value.type) {
00835                                                 case evtInt:
00836                                                         a.val[1].type = NUMBER_ST;
00837                                                         a.val[1].u.number = pivot->value.u.n;
00838                                                         break;
00839                                                 case evtStr:
00840                                                         if (pivot->value.u.s)
00841                                                                 a.val[1].u.str = pivot->value.u.s->s;
00842                                                         else
00843                                                                 a.val[1].u.str.len = 0;
00844                                                         a.val[1].type = STRING_ST;
00845                                                         break;
00846                                                 default:
00847                                                         return -1;
00848                                         }
00849                                         a.next = 0;
00850                                         init_run_actions_ctx(&ra_ctx);
00851                                         ret = do_action(&ra_ctx, &a, msg);
00852                                         if (so->oper_type == esotPop)
00853                                                 remove_stack_item(pivot);
00854                                         return ret<0?-1:1;
00855                                 }
00856                                 default:
00857                                         BUG("Bad value type (%d) for get/pop\n", so->loc.value_type);
00858                                         return -1;
00859                         }
00860                         break;
00861                 case esotXchg:
00862                         switch (so->loc.value_type) {
00863                                 case esovtRegister: {
00864                                         struct eval_value v;
00865 
00866                                         v = so->loc.u.reg->value;
00867                                         so->loc.u.reg->value = pivot->value;
00868                                         pivot->value = v;
00869                                         return 1;
00870                                 }
00871                                 default:
00872                                         BUG("Bad value type (%d) for xchg\n", so->loc.value_type);
00873                                         return -1;
00874                         }
00875                         break;
00876                 case esotInsert:
00877                 case esotAdd:
00878                 case esotPut: {
00879                         struct eval_value v;
00880                         eval_location(msg, &so->loc, &v, 0);
00881 
00882                         if (so->oper_type == esotInsert || so->oper_type == esotAdd) {
00883                                 struct stack_item *si;
00884                                 si = pkg_malloc(sizeof(*si));
00885                                 if (!si) {
00886                                         ERR(MODULE_NAME": out of memory\n");
00887                                         destroy_value(v);
00888                                         return -1;
00889                                 }
00890                                 si->value = v;
00891                                 insert_stack_item(si, pivot, so->oper_type == esotAdd);
00892                                 return 1;
00893                         }
00894                         else {
00895                                 destroy_value(pivot->value);
00896                                 pivot->value = v;
00897                                 return 1;
00898                         }
00899                         break;
00900                 }
00901                 case esotInsertValue:
00902                 case esotAddValue: {
00903                         struct eval_value v;
00904                         str s, *vals;
00905                         int i, n;
00906                         struct eval_str* es;
00907                         struct stack_item *si;
00908                         eval_location(msg, &so->loc, &v, 0);
00909                         get_as_str(&v, &s);
00910                         if ((parse_hf_values(s, &n, &vals) < 0) || n == 0) {
00911                                 destroy_value(v);
00912                                 return -1;
00913                         }
00914                         si = pkg_malloc(sizeof(*si));
00915                         if (!si) {
00916                                 ERR(MODULE_NAME": out of memory\n");
00917                                 destroy_value(v);
00918                                 return -1;
00919                         }
00920                         si->value.type = evtInt;
00921                         si->value.u.n = n;
00922                         insert_stack_item(si, pivot, so->oper_type == esotAddValue);
00923                         pivot = si;
00924                         for (i=0; i<n; i++) {
00925                                 si = pkg_malloc(sizeof(*si));
00926                                 if (!si) {
00927                                         ERR(MODULE_NAME": out of memory\n");
00928                                         destroy_value(v);
00929                                         return -1;
00930                                 }
00931                                 es = eval_str_malloc(vals+i);
00932                                 if (!es) {
00933                                         ERR(MODULE_NAME": out of memory\n");
00934                                         destroy_value(v);
00935                                         return -1;
00936                                 }
00937                                 si->value.type = evtStr;
00938                                 si->value.u.s = es;
00939                                 insert_stack_item(si, pivot, 1);
00940                                 pivot = si;
00941                         }
00942                         destroy_value(v);
00943                         return 1;
00944                 }
00945                 default:
00946                         BUG("Unexpected operation (%d)\n", so->oper_type);
00947                         return -1;
00948         }
00949 }
00950 
00951 static int eval_add_fixup( void** param, int param_no) {
00952         return fixup_stack_oper(param, param_no, esotAdd);
00953 }
00954 
00955 static int eval_insert_fixup( void** param, int param_no) {
00956         return fixup_stack_oper(param, param_no, esotInsert);
00957 }
00958 
00959 static int eval_put_fixup( void** param, int param_no) {
00960         return fixup_stack_oper(param, param_no, esotPut);
00961 }
00962 
00963 static int eval_get_fixup( void** param, int param_no) {
00964         return fixup_stack_oper(param, param_no, esotGet);
00965 }
00966 
00967 static int eval_pop_fixup( void** param, int param_no) {
00968         return fixup_stack_oper(param, param_no, esotPop);
00969 }
00970 
00971 static int eval_xchg_fixup( void** param, int param_no) {
00972         return fixup_stack_oper(param, param_no, esotXchg);
00973 }
00974 
00975 static int eval_add_value_fixup( void** param, int param_no) {
00976         return fixup_stack_oper(param, param_no, esotAddValue);
00977 }
00978 
00979 static int eval_insert_value_fixup( void** param, int param_no) {
00980         return fixup_stack_oper(param, param_no, esotInsertValue);
00981 }
00982 
00983 
00984 static int eval_remove_func(struct sip_msg *msg, char *param1, char *param2) {
00985         struct stack_item *p, *p2;
00986         int ret, len, start;
00987         struct eval_value v;
00988 
00989         if (param1) {
00990                 long l;
00991                 eval_location(msg, (struct eval_location*) param1, &v, 1);
00992                 ret = get_as_int(&v, &l);
00993                 if (ret < 0) return ret;
00994                 start = l;
00995         }
00996         else
00997                 start = 0;
00998         p = find_stack_item(start);
00999         if (p) {
01000                 if (param2) {
01001                         long l;
01002                         eval_location(msg, (struct eval_location*) param2, &v, 1);
01003                         ret = get_as_int(&v, &l);
01004                         if (ret < 0) return ret;
01005                         len = l;
01006                 }
01007                 else
01008                         len = 1;
01009 
01010                 if (start < 0) {
01011                         start = stack_no + start;
01012                         if (start < 0) start = 0;
01013                 }
01014                 else {
01015                         if (start > stack_no) start = stack_no;
01016                 }
01017                 if (len < 0) {
01018                         len = stack_no - start + len;
01019                         if (len < 0)
01020                                 len = 0;
01021                 }
01022                 else {
01023                         if (start + len > stack_no)
01024                                 len = stack_no - start;
01025                 }
01026 
01027                 for (; len > 0 && p; len--) {
01028                         p2 = p;
01029                         p = p->next;
01030                         remove_stack_item(p2);
01031                 }
01032                 return 1;
01033         }
01034         else
01035                 return -1;
01036 }
01037 
01038 static int eval_clear_func(struct sip_msg *msg, char *param1, char *param2) {
01039         int n;
01040         if (get_int_fparam(&n, msg, (fparam_t*)param1)<0) {
01041                 ERR(MODULE_NAME": eval_clear: Invalid number specified\n");
01042                 return -1;
01043         }
01044         if (n & 1)
01045                 destroy_stack();
01046         if (n & 2)
01047                 destroy_register_values();
01048         return 1;
01049 }
01050 
01051 enum {esftNone=0, esftAdd, esftSub, esftMultiplication, esftDivision, esftModulo, esftNeg, esftAbs, esftSgn, esftDec, esftInc,
01052 esftConcat, esftSubstr, esftStrLen, esftStrStr, esftStrDel, esftStrUpper, esftStrLower,
01053 esftCastAsInt, esftCastAsStr,
01054 esftValueAt, esftValueUris, esftValueRev, esftSubValue, esftValueCount, esftValueConcat, esftStrValueAt,
01055 esftGetUri,
01056 esftAnd, esftOr, esftNot, esftBitAnd, esftBitOr, esftBitNot, esftBitXor, esftEQ, esftNE, esftGT, esftGE, esftLW, esftLE};
01057 
01058 struct eval_function_def {
01059         int type;
01060         char *name;
01061         int arg_no;
01062 };
01063 
01064 static struct eval_function_def eval_functions[] = {
01065         {esftAdd, "+", 2},
01066         {esftSub, "-", 2},
01067         {esftMultiplication, "*", 2},
01068         {esftDivision, "/", 2},
01069         {esftModulo, "%", 2},
01070         {esftNeg, "neg", 1},
01071         {esftAbs, "abs", 1},
01072         {esftDec, "dec", 1},
01073         {esftInc, "inc", 1},
01074         {esftSgn, "sgn", 1},
01075         {esftConcat, "concat", 2},
01076         {esftSubstr, "substr", 3},
01077         {esftStrLen, "strlen", 1},
01078         {esftStrStr, "strstr", 2},
01079         {esftStrDel, "strdel", 3},
01080         {esftStrUpper, "strupper", 1},
01081         {esftStrLower, "strlower", 1},
01082         {esftCastAsInt, "(int)", 1},
01083         {esftCastAsStr, "(str)", 1},
01084         {esftValueAt, "valat", 2},
01085         {esftValueUris, "valuris", 1},
01086         {esftValueRev, "valrev", 1},
01087         {esftSubValue, "subval", 3},
01088         {esftValueCount, "valcount", 1},
01089         {esftValueConcat, "valconcat", 1},
01090         {esftStrValueAt, "strvalat", 2},
01091         {esftGetUri, "geturi", 1},
01092         {esftAnd, "&&", 2},
01093         {esftOr, "||", 2},
01094         {esftNot, "!", 1},
01095         {esftBitAnd, "&", 2},
01096         {esftBitOr, "|", 2},
01097         {esftBitNot, "~", 1},
01098         {esftBitXor, "^", 2},
01099 
01100         {esftEQ, "==", 2},
01101         {esftNE, "!=", 2},
01102         {esftGT, ">", 2},
01103         {esftGE, ">=", 2},
01104         {esftLW, "<", 2},
01105         {esftLE, "<=", 2},
01106 
01107         {esftNone, NULL}
01108 };
01109 
01110 struct eval_function {
01111         int resolved;  /* is oper.d valid ? */
01112         union {
01113                 struct eval_function_def *d;
01114                 struct eval_location loc;
01115         } oper;
01116         struct eval_function* next;
01117 };
01118 
01119 static int eval_stack_func_fixup( void** param, int param_no) {
01120         char *c,  *c2;
01121         struct eval_function_def* d;
01122         struct eval_function **p, *head;
01123         if (param_no == 2) {
01124                 return fixup_location_12(param, param_no);
01125         }
01126 
01127         head = 0;
01128         p = &head;
01129         c = *param;
01130         while (*c) {
01131                 str s;
01132                 struct eval_location so;
01133                 while( (*c<=' ' || *c == ',') && *c ) c++;
01134                 if (*c == '\0')
01135                         break;
01136                 c2 = c;
01137                 while (*c && *c!=',') c++;
01138                 while (c > c2 && *(c-1) <= ' ') c--;
01139 
01140                 s.s = c2;
01141                 s.len = c-c2;
01142 
01143                 if (parse_location(s, &so) < 0) {
01144                         ERR(MODULE_NAME": parse operation error near '%s'\n", c2);
01145                         return E_CFG;
01146                 }
01147                 *p = pkg_malloc(sizeof(**p));
01148                 if (!*p) return E_OUT_OF_MEM;
01149                 (*p)->next = 0;
01150                 switch (so.value_type) {
01151                         case esovtStr:
01152                                 for (d=eval_functions; d->type; d++) {
01153                                         if (strlen(d->name) == so.u.s.s.len && strncasecmp(d->name, so.u.s.s.s, so.u.s.s.len)==0) {
01154                                                 (*p)->oper.d = d;
01155                                                 break;
01156                                         }
01157                                 }
01158                                 if (!d->type) {
01159                                         ERR(MODULE_NAME": unknown eval function near '%s'\n", so.u.s.s.s);
01160                                         return E_CFG;
01161                                 }
01162                                 (*p)->resolved = 1;
01163                                 break;
01164                         case esovtAvp:
01165                         case esovtXStr:
01166                         case esovtRegister:
01167                         case esovtSelect:
01168                         case esovtFunc:
01169                                 (*p)->oper.loc = so;
01170                                 (*p)->resolved = 0;
01171                                 break;
01172                         default:
01173                                 ERR(MODULE_NAME": location %d not allowed\n", so.value_type);
01174                                 return E_CFG;
01175                 }
01176                 p = &(*p)->next;
01177 
01178         }
01179         *param = head;
01180         return 0;
01181 }
01182 
01183 #ifndef _GNU_SOURCE
01184 void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);
01185 #endif
01186 
01187 static int eval_stack_func_func(struct sip_msg *msg, char *param1, char *param2) {
01188         struct eval_function *f;
01189         struct stack_item *pivot;
01190         struct eval_function_def *d;
01191         int stack_idx = 0;
01192         int ret = -1;
01193 
01194         if (param2) {
01195                 long l;
01196                 int ret;
01197                 struct eval_value v;
01198                 eval_location(msg, (struct eval_location*) param2, &v, 1);
01199                 ret = get_as_int(&v, &l);
01200                 if (ret < 0) return ret;
01201                 stack_idx = l;
01202         }
01203 
01204         for (f = (struct eval_function*) param1; f; f=f->next, ret = 1) {
01205                 if (f->resolved) {
01206                         d = f->oper.d;
01207                 }
01208                 else {
01209                         str fn;
01210                         struct eval_value v;
01211                         eval_location(msg, &f->oper.loc, &v, 1);
01212                         get_as_str(&v, &fn);
01213                         for (d=eval_functions; d->type; d++) {
01214                                 if (strlen(d->name) == fn.len && strncasecmp(d->name, fn.s, fn.len)==0) {
01215                                         break;
01216                                 }
01217                         }
01218                         if (!d->type) {
01219                                 ERR(MODULE_NAME": unknown eval function '%.*s'\n", fn.len, fn.s);
01220                                 return -1;
01221                         }
01222                 }
01223                 DEBUG(MODULE_NAME": eval_oper: %s, stack_idx: %d, stack_no: %d\n", d->name, stack_idx, stack_no);
01224                 if ( ((stack_idx >= 0) && (stack_idx+d->arg_no > stack_no)) ||
01225                      ((stack_idx <  0) && (stack_no+stack_idx < 0 || stack_no+stack_idx+d->arg_no > stack_no)) ) {
01226                         ERR(MODULE_NAME": operation out of stack range\n");
01227                         return -1;
01228                 }
01229                 pivot = find_stack_item(stack_idx);
01230                 if (!pivot) {
01231                         BUG("stack test error\n");
01232                         return -1;
01233                 }
01234                 switch (d->type) {
01235 
01236                         case esftAdd:
01237                         case esftSub:
01238                         case esftMultiplication:
01239                         case esftDivision:
01240                         case esftModulo:
01241                         case esftAnd:
01242                         case esftOr:
01243                         case esftBitAnd:
01244                         case esftBitOr:
01245                         case esftBitXor: {
01246                                 long a, b;
01247                                 if (get_as_int(&pivot->value, &a) < 0) return -1;
01248                                 if (get_as_int(&pivot->next->value, &b) < 0) return -1;
01249                                 switch (d->type) {
01250                                         case esftAdd:
01251                                                 a = a + b;
01252                                                 break;
01253                                         case esftSub:
01254                                                 a = a - b;
01255                                                 break;
01256                                         case esftMultiplication:
01257                                                 a = a * b;
01258                                                 break;
01259                                         case esftDivision:
01260                                                 if (b == 0) {
01261                                                         ERR(MODULE_NAME": division by zero\n");
01262                                                         return -1;
01263                                                 }
01264                                                 a = a / b;
01265                                                 break;
01266                                         case esftModulo:
01267                                                 if (b == 0) {
01268                                                         ERR(MODULE_NAME": division by zero\n");
01269                                                         return -1;
01270                                                 }
01271                                                 a = a % b;
01272                                                 break;
01273                                         case esftAnd:
01274                                                 a = a && b;
01275                                                 break;
01276                                         case esftOr:
01277                                                 a = a || b;
01278                                                 break;
01279                                         case esftBitAnd:
01280                                                 a = a & b;
01281                                                 break;
01282                                         case esftBitOr:
01283                                                 a = a | b;
01284                                                 break;
01285                                         case esftBitXor:
01286                                                 a = a ^ b;
01287                                                 break;
01288                                 }
01289                                 destroy_value(pivot->value);
01290                                 pivot->value.type = evtInt;
01291                                 pivot->value.u.n = a;
01292                                 remove_stack_item(pivot->next);
01293                                 break;
01294                         }
01295                         case esftNeg:
01296                         case esftAbs:
01297                         case esftSgn:
01298                         case esftDec:
01299                         case esftInc:
01300                         case esftNot:
01301                         case esftBitNot:
01302                         case esftCastAsInt: {
01303                                 long a;
01304                                 if (get_as_int(&pivot->value, &a) < 0) return -1;
01305                                 switch (d->type) {
01306                                         case esftNeg:
01307                                                 a = -a;
01308                                                 break;
01309                                         case esftAbs:
01310                                                 a = abs(a);
01311                                                 break;
01312                                         case esftSgn:
01313                                                 if (a < 0)
01314                                                         a = -1;
01315                                                 else if (a > 0)
01316                                                         a = 1;
01317                                                 else
01318                                                         a = 0;
01319                                                 break;
01320                                         case esftDec:
01321                                                 a--;
01322                                                 break;
01323                                         case esftInc:
01324                                                 a++;
01325                                                 break;
01326                                         case esftNot:
01327                                                 a = !a;
01328                                                 break;
01329                                         case esftBitNot:
01330                                                 a = ~a;
01331                                                 break;
01332                                         case esftCastAsInt:
01333                                                 break;
01334                                 }
01335                                 destroy_value(pivot->value);
01336                                 pivot->value.type = evtInt;
01337                                 pivot->value.u.n = a;
01338                                 break;
01339                         }
01340                         case esftCastAsStr:
01341                                 if (pivot->value.type != evtStr) {
01342                                         str s;
01343                                         get_as_str(&pivot->value, &s);
01344                                         destroy_value(pivot->value);
01345                                         pivot->value.u.s = eval_str_malloc(&s);
01346                                         if (!pivot->value.u.s) {
01347                                                 ERR(MODULE_NAME": out of memory\n");
01348                                                 return -1;
01349                                         }
01350                                         pivot->value.type = evtStr;
01351                                 }
01352                                 break;
01353                         case esftEQ:
01354                         case esftNE:
01355                         case esftGT:
01356                         case esftGE:
01357                         case esftLW:
01358                         case esftLE: {
01359                                 long a;
01360                                 if (pivot->value.type == evtStr || pivot->next->value.type == evtStr) {
01361                                         str s1, s2;
01362                                         int l;
01363                                         get_as_str(&pivot->value, &s1);
01364                                         get_as_str(&pivot->next->value, &s2);
01365                                         l = (s1.len < s2.len)?s1.len:s2.len;
01366                                         if (l > 0)
01367                                                 a = strncasecmp(s1.s, s2.s, l);
01368                                         else
01369                                                 a = 0;
01370                                         switch (d->type) {
01371                                                 case esftEQ:
01372                                                         a = a == 0 && s1.len == s2.len;
01373                                                         break;
01374                                                 case esftNE:
01375                                                         a = a != 0 || s1.len != s2.len;
01376                                                         break;
01377                                                 case esftGT:
01378                                                         a = a > 0 || (a == 0 && s1.len > s2.len);
01379                                                         break;
01380                                                 case esftGE:
01381                                                         a = a > 0 || (a == 0 && s1.len >= s2.len);
01382                                                         break;
01383                                                 case esftLW:
01384                                                         a = a < 0 || (a == 0 && s1.len < s2.len);
01385                                                         break;
01386                                                 case esftLE:
01387                                                         a = a < 0 || (a == 0 && s1.len <= s2.len);
01388                                                         break;
01389                                         }
01390                                 }
01391                                 else {
01392                                         long b;
01393                                         if (get_as_int(&pivot->value, &a) < 0) return -1;
01394                                         if (get_as_int(&pivot->next->value, &b) < 0) return -1;
01395                                         switch (d->type) {
01396                                                 case esftEQ:
01397                                                         a = a == b;
01398                                                         break;
01399                                                 case esftNE:
01400                                                         a = a != b;
01401                                                         break;
01402                                                 case esftGT:
01403                                                         a = a > b;
01404                                                         break;
01405                                                 case esftGE:
01406                                                         a = a >= b;
01407                                                         break;
01408                                                 case esftLW:
01409                                                         a = a < b;
01410                                                         break;
01411                                                 case esftLE:
01412                                                         a = a <= b;
01413                                                         break;
01414                                         }
01415                                 }
01416                                 destroy_value(pivot->value);
01417                                 pivot->value.type = evtInt;
01418                                 pivot->value.u.n = a;
01419                                 remove_stack_item(pivot->next);
01420                                 break;
01421                         }
01422                         case esftConcat: {
01423                                 char buf[25];
01424                                 str s, s1, s2;
01425                                 struct eval_str* es;
01426                                 get_as_str(&pivot->value, &s1);
01427                                 if (pivot->value.type == evtInt && pivot->next->value.type == evtInt) {
01428                                         memcpy(buf, s1.s, s1.len);  /* result in static buffer */
01429                                         s1.s = buf;
01430                                 }
01431                                 get_as_str(&pivot->next->value, &s2);
01432                                 s.len = s1.len + s2.len;
01433                                 s.s = 0;
01434                                 es = eval_str_malloc(&s);
01435                                 if (!es) {
01436                                         ERR(MODULE_NAME": out of memory\n");
01437                                         return -1;
01438                                 }
01439                                 memcpy(s.s, s1.s, s1.len);
01440                                 memcpy(s.s+s1.len, s2.s, s2.len);
01441                                 destroy_value(pivot->value);
01442                                 pivot->value.type = evtStr;
01443                                 pivot->value.u.s = es;
01444                                 remove_stack_item(pivot->next);
01445                                 break;
01446                         }
01447                         case esftSubstr: {
01448                                 long start, len;
01449                                 str s1;
01450                                 struct eval_str* es;
01451                                 get_as_str(&pivot->value, &s1);
01452                                 if (get_as_int(&pivot->next->value, &start) < 0) return -1;
01453                                 if (get_as_int(&pivot->next->next->value, &len) < 0) return -1;
01454 
01455                                 if (start < 0) {
01456                                         start = s1.len + start;
01457                                         if (start < 0) start = 0;
01458                                 }
01459                                 else {
01460                                         if (start > s1.len) start = s1.len;
01461                                 }
01462                                 if (len < 0) {
01463                                         len = s1.len - start + len;
01464                                         if (len < 0)
01465                                                 len = 0;
01466                                 }
01467                                 else {
01468                                         if (start + len > s1.len)
01469                                                 len = s1.len - start;
01470                                 }
01471                                 s1.s += start;
01472                                 s1.len = len;
01473                                 es = eval_str_malloc(&s1);
01474                                 if (!es) {
01475                                         ERR(MODULE_NAME": out of memory\n");
01476                                         return -1;
01477                                 }
01478                                 destroy_value(pivot->value);
01479                                 pivot->value.type = evtStr;
01480                                 pivot->value.u.s = es;
01481                                 remove_stack_item(pivot->next);
01482                                 remove_stack_item(pivot->next);
01483                                 break;
01484                         }
01485                         case esftStrLen: {
01486                                 long len;
01487                                 str s1;
01488                                 get_as_str(&pivot->value, &s1);
01489                                 len = s1.len;
01490                                 destroy_value(pivot->value);
01491                                 pivot->value.type = evtInt;
01492                                 pivot->value.u.n = len;
01493                                 break;
01494                         }
01495                         case esftStrStr: {
01496                                 char buf[25], *p;
01497                                 str s1, s2;
01498 
01499                                 get_as_str(&pivot->value, &s1);
01500                                 if (pivot->value.type == evtInt && pivot->next->value.type == evtInt) {
01501                                         memcpy(buf, s1.s, s1.len);  /* result in static buffer */
01502                                         s1.s = buf;
01503                                 }
01504                                 get_as_str(&pivot->next->value, &s2);
01505                                 p = (char *) memmem(s1.s, s1.len, s2.s, s2.len);
01506                                 destroy_value(pivot->value);
01507                                 pivot->value.type = evtInt;
01508                                 pivot->value.u.n = p?p-s1.s:-1;
01509                                 remove_stack_item(pivot->next);
01510                                 break;
01511                         }
01512                         case esftStrDel: {
01513                                 long start, len;
01514                                 str s1, s;
01515                                 struct eval_str* es;
01516                                 get_as_str(&pivot->value, &s1);
01517                                 if (get_as_int(&pivot->next->value, &start) < 0) return -1;
01518                                 if (get_as_int(&pivot->next->next->value, &len) < 0) return -1;
01519 
01520                                 if (start < 0) {
01521                                         start = s1.len + start;
01522                                         if (start < 0) start = 0;
01523                                 }
01524                                 else {
01525                                         if (start > s1.len) start = s1.len;
01526                                 }
01527                                 if (len < 0) {
01528                                         len = s1.len - start + len;
01529                                         if (len < 0)
01530                                                 len = 0;
01531                                 }
01532                                 else {
01533                                         if (start + len > s1.len)
01534                                                 len = s1.len - start;
01535                                 }
01536                                 s.s = 0;
01537                                 s.len = s1.len - len;
01538                                 es = eval_str_malloc(&s);
01539                                 if (!es) {
01540                                         ERR(MODULE_NAME": out of memory\n");
01541                                         return -1;
01542                                 }
01543                                 if (start > 0)
01544                                         memcpy(s.s, s1.s, start);
01545                                 memcpy(s.s+start, s1.s+start+len, s1.len-(start+len));
01546                                 destroy_value(pivot->value);
01547                                 pivot->value.type = evtStr;
01548                                 pivot->value.u.s = es;
01549                                 remove_stack_item(pivot->next);
01550                                 remove_stack_item(pivot->next);
01551                                 break;
01552                         }
01553                         case esftStrUpper:
01554                         case esftStrLower: {
01555                                 str s1;
01556                                 int i;
01557                                 struct eval_str* es;
01558                                 get_as_str(&pivot->value, &s1);
01559 
01560                                 es = eval_str_malloc(&s1);
01561                                 if (!es) {
01562                                         ERR(MODULE_NAME": out of memory\n");
01563                                         return -1;
01564                                 }
01565                                 for (i=0; i<es->s.len; i++)
01566                                         es->s.s[i] = (d->type == esftStrUpper) ? toupper(es->s.s[i]) : tolower(es->s.s[i]);
01567                                 destroy_value(pivot->value);
01568                                 pivot->value.type = evtStr;
01569                                 pivot->value.u.s = es;
01570                                 break;
01571                         }
01572                         case esftValueAt: {
01573                                 str s1, *vals;
01574                                 long idx;
01575                                 int n;
01576                                 struct eval_str* es;
01577 
01578                                 get_as_str(&pivot->value, &s1);
01579                                 if (get_as_int(&pivot->next->value, &idx) < 0) return -1;
01580                                 if (parse_hf_values(s1, &n, &vals) < 0) return -1;
01581                                 if (idx < 0|| idx >= n) {
01582                                         ERR(MODULE_NAME": index (%ld) of of range (%d)\n", idx, n);
01583                                         return -1;
01584                                 }
01585                                 es = eval_str_malloc(vals+idx);
01586                                 if (!es) {
01587                                         ERR(MODULE_NAME": out of memory\n");
01588                                         return -1;
01589                                 }
01590                                 destroy_value(pivot->value);
01591                                 pivot->value.type = evtStr;
01592                                 pivot->value.u.s = es;
01593                                 remove_stack_item(pivot->next);
01594                                 break;
01595                         }
01596                         case esftStrValueAt: {
01597                                 char buf[25];
01598                                 str s1, s2, *vals;
01599                                 int i, n;
01600 
01601                                 get_as_str(&pivot->value, &s1);
01602                                 if (pivot->value.type == evtInt && pivot->next->value.type == evtInt) {
01603                                         memcpy(buf, s1.s, s1.len);  /* result in static buffer */
01604                                         s1.s = buf;
01605                                 }
01606                                 get_as_str(&pivot->next->value, &s2);
01607                                 if (parse_hf_values(s1, &n, &vals) < 0) return -1;
01608                                 for (i=0; i<n; i++) {
01609                                         if (s2.len == vals[i].len && strncmp(s2.s, vals[i].s, s2.len) == 0)
01610                                                 break;
01611                                 }
01612                                 destroy_value(pivot->value);
01613                                 pivot->value.type = evtInt;
01614                                 pivot->value.u.n = (i>=n)?-1:i;
01615                                 remove_stack_item(pivot->next);
01616                                 break;
01617                         }
01618                         case esftValueCount: {
01619                                 str s1, *vals;
01620                                 int n;
01621 
01622                                 get_as_str(&pivot->value, &s1);
01623                                 if (parse_hf_values(s1, &n, &vals) < 0) return -1;
01624                                 destroy_value(pivot->value);
01625                                 pivot->value.type = evtInt;
01626                                 pivot->value.u.n = n;
01627                                 break;
01628                         }
01629                         case esftSubValue: {
01630                                 long start, len;
01631                                 int i, n, pos;
01632                                 str s1, s, *vals;
01633                                 struct eval_str* es;
01634                                 get_as_str(&pivot->value, &s1);
01635                                 if (get_as_int(&pivot->next->value, &start) < 0) return -1;
01636                                 if (get_as_int(&pivot->next->next->value, &len) < 0) return -1;
01637                                 if (parse_hf_values(s1, &n, &vals) < 0) return -1;
01638 
01639                                 if (start < 0) {
01640                                         start = n + start;
01641                                         if (start < 0) start = 0;
01642                                 }
01643                                 else {
01644                                         if (start > n) start = n;
01645                                 }
01646                                 if (len < 0) {
01647                                         len = n - start + len;
01648                                         if (len < 0)
01649                                                 len = 0;
01650                                 }
01651                                 else {
01652                                         if (start + len > n)
01653                                                 len = n - start;
01654                                 }
01655                                 s.len = 0;
01656                                 for (i=0; i<len; i++) {
01657                                         s.len += vals[start+i].len+1/*delim*/;
01658                                 }
01659                                 if (s.len)
01660                                         s.len--;
01661                                 s.s = 0;
01662                                 es = eval_str_malloc(&s);
01663                                 if (!es) {
01664                                         ERR(MODULE_NAME": out of memory\n");
01665                                         return -1;
01666                                 }
01667                                 for (i=0, pos=0; i<len; i++) {
01668                                         if (pos > 0)
01669                                                 s.s[pos++] = ',';
01670                                         memcpy(s.s+pos, vals[start+i].s, vals[start+i].len);
01671                                         pos += vals[start+i].len;
01672                                 }
01673 
01674                                 destroy_value(pivot->value);
01675                                 pivot->value.type = evtStr;
01676                                 pivot->value.u.s = es;
01677                                 remove_stack_item(pivot->next);
01678                                 remove_stack_item(pivot->next);
01679                                 break;
01680                         }
01681                         case esftValueConcat: {
01682                                 long n;
01683                                 int i, pos;
01684                                 str s1, s;
01685                                 struct eval_str* es;
01686                                 struct stack_item *si;
01687 
01688                                 if (get_as_int(&pivot->value, &n) < 0) return -1;
01689                                 for (si=pivot->next, s.len=0, i=0; i<n && si; i++, si=si->next) {
01690                                         get_as_str(&si->value, &s1);
01691                                         s.len += s1.len+1;
01692                                 }
01693                                 if (s.len)
01694                                         s.len--;
01695                                 s.s = 0;
01696                                 es = eval_str_malloc(&s);
01697                                 if (!es) {
01698                                         ERR(MODULE_NAME": out of memory\n");
01699                                         return -1;
01700                                 }
01701                                 for (si=pivot->next, i=0, pos=0; i<n && si; i++, si=si->next) {
01702                                         if (pos > 0)
01703                                                 s.s[pos++] = ',';
01704                                         get_as_str(&si->value, &s1);
01705                                         memcpy(s.s+pos, s1.s, s1.len);
01706                                         pos += s1.len;
01707                                 }
01708 
01709                                 destroy_value(pivot->value);
01710                                 pivot->value.type = evtStr;
01711                                 pivot->value.u.s = es;
01712                                 for (si=pivot->next, i=0; i<n && si; i++) {
01713                                         struct stack_item *si2;
01714                                         si2 = si;
01715                                         si=si->next;
01716                                         remove_stack_item(si2);
01717                                 }
01718                                 break;
01719 
01720                         }
01721                         case esftValueRev: {
01722                                 int i, n, pos;
01723                                 str s1, s, *vals;
01724                                 struct eval_str* es;
01725                                 get_as_str(&pivot->value, &s1);
01726                                 if (parse_hf_values(s1, &n, &vals) < 0) return -1;
01727 
01728                                 s.len = 0;
01729                                 for (i=0; i<n; i++) {
01730                                         s.len += vals[i].len+1/*delim*/;
01731                                 }
01732                                 if (s.len)
01733                                         s.len--;
01734                                 s.s = 0;
01735                                 es = eval_str_malloc(&s);
01736                                 if (!es) {
01737                                         ERR(MODULE_NAME": out of memory\n");
01738                                         return -1;
01739                                 }
01740                                 for (i=n-1, pos=0; i>=0; i--) {
01741                                         if (pos > 0)
01742                                                 s.s[pos++] = ',';
01743                                         memcpy(s.s+pos, vals[i].s, vals[i].len);
01744                                         pos += vals[i].len;
01745                                 }
01746 
01747                                 destroy_value(pivot->value);
01748                                 pivot->value.type = evtStr;
01749                                 pivot->value.u.s = es;
01750                                 break;
01751                         }
01752                         case esftValueUris: {
01753                                 int i, n, pos;
01754                                 str s1, s, *vals;
01755                                 struct eval_str* es;
01756                                 get_as_str(&pivot->value, &s1);
01757                                 if (parse_hf_values(s1, &n, &vals) < 0) return -1;
01758 
01759                                 s.len = 0;
01760                                 for (i=0; i<n; i++) {
01761                                         s.len += vals[i].len+1/*delim*/;
01762                                 }
01763                                 if (s.len)
01764                                         s.len--;
01765                                 s.s = 0;
01766                                 es = eval_str_malloc(&s);
01767                                 if (!es) {
01768                                         ERR(MODULE_NAME": out of memory\n");
01769                                         return -1;
01770                                 }
01771                                 for (i=0, pos=0; i<n; i++) {
01772                                         str hval1, huri;
01773                                         if (pos > 0)
01774                                                 s.s[pos++] = ',';
01775                                         hval1 = *(vals+i);
01776                                         get_uri_and_skip_until_params(&hval1, &huri);
01777                                         if (huri.len) {
01778                                         /* TODO: normalize uri, lowercase except quoted params */
01779                                                 memcpy(s.s+pos, huri.s, huri.len);
01780                                                 pos += huri.len;
01781                                         }
01782                                 }
01783                                 es->s.len = pos;
01784 
01785                                 destroy_value(pivot->value);
01786                                 pivot->value.type = evtStr;
01787                                 pivot->value.u.s = es;
01788                                 break;
01789                         }
01790                         case esftGetUri: {
01791                                 str s1, huri;
01792                                 struct eval_str* es;
01793                                 get_as_str(&pivot->value, &s1);
01794                                 get_uri_and_skip_until_params(&s1, &huri);
01795                                 if (huri.len && *(huri.s) == '<') {
01796                                         huri.s++;       /* strip < & > */
01797                                         huri.len-=2;
01798                                 }
01799                                 es = eval_str_malloc(&huri);
01800                                 if (!es) {
01801                                         ERR(MODULE_NAME": out of memory\n");
01802                                         return -1;
01803                                 }
01804                                 destroy_value(pivot->value);
01805                                 pivot->value.type = evtStr;
01806                                 pivot->value.u.s = es;
01807                                 break;
01808                         }
01809                         default:
01810                                 BUG("Bad operation %d\n", d->type);
01811                                 return -1;
01812                 }
01813         }
01814         return ret;
01815 }
01816 
01817 static int eval_while_fixup(void **param, int param_no) {
01818 
01819         if (param_no == 2) {
01820                 return fixup_location_12(param, param_no);
01821         }
01822         else if (param_no == 1) {
01823                 int n;
01824                 n = route_get(&main_rt, (char*) *param);
01825                 if (n == -1) {
01826                         ERR(MODULE_NAME": eval_while: bad route\n");
01827                         return E_CFG;
01828                 }
01829                 pkg_free(*param);
01830                 *param=(void*) (intptr_t) n;
01831         }
01832         return 0;
01833 }
01834 
01835 static int eval_while_func(struct sip_msg *msg, char *route_no, char *param2) {
01836         int ret, idx;
01837         struct stack_item *pivot;
01838         struct run_act_ctx ra_ctx;
01839 
01840         if (param2) {
01841                 long l;
01842                 struct eval_value v;
01843                 eval_location(msg, (struct eval_location*) param2, &v, 1);
01844                 ret = get_as_int(&v, &l);
01845                 if (ret < 0) return ret;
01846                 idx = l;
01847         }
01848         else {
01849                 idx = 0;      /* default values */
01850         }
01851 
01852         ret = -1;
01853         while (1) {
01854                 pivot = find_stack_item(idx);
01855                 if (!pivot) break;
01856                 if (get_as_bool(&pivot->value) <= 0) break;
01857                 if ((intptr_t)route_no >= main_rt.idx) {
01858                         BUG("invalid routing table number #%d of %d\n", (int)(intptr_t) route_no, main_rt.idx);
01859                         return -1;
01860                 }
01861                 if (!main_rt.rlist[(intptr_t) route_no]) {
01862                         WARN(MODULE_NAME": route not declared (hash:%d)\n", (int)(intptr_t) route_no);
01863                         return -1;
01864                 }
01865                 /* exec the routing script */
01866                 init_run_actions_ctx(&ra_ctx);
01867                 ret = run_actions(&ra_ctx, main_rt.rlist[(intptr_t) route_no], msg);
01868                 if (ret <= 0) break;
01869         }
01870         return ret;
01871 }
01872 
01873 static int eval_while_stack_func(struct sip_msg *msg, char *route_no, char *param2) {
01874         int ret, count;
01875         struct run_act_ctx ra_ctx;
01876         
01877         if (param2) {
01878                 long l;
01879                 struct eval_value v;
01880                 eval_location(msg, (struct eval_location*) param2, &v, 1);
01881                 ret = get_as_int(&v, &l);
01882                 if (ret < 0) return ret;
01883                 count = l;
01884         }
01885         else {
01886                 count = 0;      /* default values */
01887         }
01888         ret = -1;
01889         while ((count >= 0 && stack_no > count) || (count < 0 && stack_no < -count)) {
01890                 if ((intptr_t)route_no >= main_rt.idx) {
01891                         BUG("invalid routing table number #%d of %d\n", (int)(intptr_t) route_no, main_rt.idx);
01892                         return -1;
01893                 }
01894                 if (!main_rt.rlist[(intptr_t) route_no]) {
01895                         WARN(MODULE_NAME": route not declared (hash:%d)\n", (int)(intptr_t) route_no);
01896                         return -1;
01897                 }
01898                 /* exec the routing script */
01899                 init_run_actions_ctx(&ra_ctx);
01900                 ret = run_actions(&ra_ctx, main_rt.rlist[(intptr_t) route_no], msg);
01901                 if (ret <= 0) break;
01902         }
01903         return ret;
01904 }
01905 
01906 /* select functions */
01907 static int sel_value2str(str* res, struct eval_value *v, int force_copy) {
01908         res->len = 0;
01909         switch (v->type) {
01910                 case evtInt: {
01911                         char buf[30];
01912                         res->len = snprintf(buf, sizeof(buf)-1, "%ld", v->u.n);
01913                         res->s = get_static_buffer(res->len);
01914                         if (res->s) 
01915                                 memcpy(res->s, buf, res->len);
01916                         else
01917                                 res->len = 0;
01918                         break;
01919                 }
01920                 case evtStr:
01921                         if (v->u.s) {
01922                                 *res = v->u.s->s;
01923                                 if (force_copy && res->len) {
01924                                         res->s = get_static_buffer(res->len);
01925                                         if (res->s)
01926                                                 memcpy(res->s, v->u.s->s.s, res->len);
01927                                         else
01928                                                 res->len = 0;
01929                                 }
01930                         }
01931                         break;
01932         }
01933         return 0;
01934 }
01935 
01936 static int sel_eval(str* res, select_t* s, struct sip_msg* msg) {  /* dummy */
01937         return 0;
01938 }
01939 
01940 static int sel_register(str* res, select_t* s, struct sip_msg* msg) {
01941         if (msg == 0) {
01942                 struct register_item *p = find_register(s->params[2].v.s.s, s->params[2].v.s.len);
01943                 if (p == 0) {
01944                         ERR(MODULE_NAME": select: register '%.*s' not found\n", s->params[2].v.s.len, s->params[2].v.s.s);
01945                         return E_CFG;
01946                 }
01947                 s->params[2].v.p = p;
01948                 s->params[2].type = SEL_PARAM_PTR;
01949         }
01950         else {
01951                 return sel_value2str(res, &((struct register_item *)s->params[2].v.p)->value, 0);
01952         }
01953         return 0;
01954 }
01955 
01956 static int sel_get_and_remove(str* res, select_t* s, struct sip_msg* msg) {
01957         struct stack_item* p;
01958         res->len = 0;
01959         p = find_stack_item(s->params[2].v.i);
01960         if (p) {
01961                 sel_value2str(res, &p->value, 1);
01962                 remove_stack_item(p);
01963         }
01964         return 0;
01965 }
01966 
01967 static int sel_get(str* res, select_t* s, struct sip_msg* msg) {
01968         struct stack_item* p;
01969         res->len = 0;
01970         p = find_stack_item(s->params[2].v.i);
01971         if (p) {
01972                 sel_value2str(res, &p->value, 0);
01973         }
01974         return 0;
01975 }
01976 
01977 SELECT_F(select_any_nameaddr)
01978 SELECT_F(select_any_uri)
01979 SELECT_F(select_anyheader_params)
01980 
01981 select_row_t sel_declaration[] = {
01982         { NULL, SEL_PARAM_STR, STR_STATIC_INIT(MODULE_NAME), sel_eval, SEL_PARAM_EXPECTED},
01983 
01984         { sel_eval, SEL_PARAM_STR, STR_STATIC_INIT("pop"), sel_get_and_remove, CONSUME_NEXT_INT },
01985         { sel_eval, SEL_PARAM_STR, STR_STATIC_INIT("get"), sel_get, CONSUME_NEXT_INT },
01986         { sel_eval, SEL_PARAM_STR, STR_STATIC_INIT("reg"), sel_register, CONSUME_NEXT_STR|FIXUP_CALL },
01987 
01988         { sel_get, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"), select_any_nameaddr, NESTED | CONSUME_NEXT_STR},
01989         { sel_get, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_any_uri, NESTED | CONSUME_NEXT_STR},
01990         { sel_get, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_anyheader_params, NESTED},
01991         { sel_register, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"), select_any_nameaddr, NESTED | CONSUME_NEXT_STR},
01992         { sel_register, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_any_uri, NESTED | CONSUME_NEXT_STR},
01993         { sel_register, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_anyheader_params, NESTED},
01994 
01995         /* for backward compatability only, use @sys.unique */
01996         { sel_eval, SEL_PARAM_STR, STR_STATIC_INIT("uuid"), select_sys_unique, 0},
01997 
01998         { NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
01999 };
02000 
02001 
02002 static int mod_init() {
02003 
02004         register_script_cb(mod_pre_script_cb, REQUEST_CB | ONREPLY_CB | PRE_SCRIPT_CB, 0);
02005         register_select_table(sel_declaration);
02006         return 0;
02007 }
02008 
02009 static int child_init(int rank) {
02010 
02011         return 0;
02012 }
02013 
02014 static void destroy_mod(void) {
02015         struct register_item *p;
02016         destroy_stack();
02017         destroy_register_values();
02018         while (registers) {
02019                 p = registers;
02020                 registers = registers->next;
02021                 pkg_free(p);
02022         }
02023 }
02024 
02025 /*
02026  * Exported functions
02027  */
02028 static cmd_export_t cmds[] = {
02029         {MODULE_NAME"_add", eval_stack_oper_func, 2, eval_add_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02030         {MODULE_NAME"_add", eval_stack_oper_func, 1, eval_add_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02031         {MODULE_NAME"_push", eval_stack_oper_func, 2, eval_add_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02032         {MODULE_NAME"_push", eval_stack_oper_func, 1, eval_add_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02033         {MODULE_NAME"_insert", eval_stack_oper_func, 2, eval_insert_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02034         {MODULE_NAME"_insert", eval_stack_oper_func, 1, eval_insert_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02035         {MODULE_NAME"_xchg", eval_stack_oper_func, 2, eval_xchg_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02036         {MODULE_NAME"_xchg", eval_stack_oper_func, 1, eval_xchg_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02037         {MODULE_NAME"_get", eval_stack_oper_func, 2, eval_get_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02038         {MODULE_NAME"_get", eval_stack_oper_func, 1, eval_get_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02039         {MODULE_NAME"_put", eval_stack_oper_func, 2, eval_put_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02040         {MODULE_NAME"_put", eval_stack_oper_func, 1, eval_put_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02041         {MODULE_NAME"_pop", eval_stack_oper_func, 2, eval_pop_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02042         {MODULE_NAME"_pop", eval_stack_oper_func, 1, eval_pop_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02043         {MODULE_NAME"_add_value", eval_stack_oper_func, 2, eval_add_value_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02044         {MODULE_NAME"_add_value", eval_stack_oper_func, 1, eval_add_value_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02045         {MODULE_NAME"_insert_value", eval_stack_oper_func, 2, eval_insert_value_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02046         {MODULE_NAME"_insert_value", eval_stack_oper_func, 1, eval_insert_value_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02047 
02048         {MODULE_NAME"_remove", eval_remove_func, 0, fixup_location_12, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02049         {MODULE_NAME"_remove", eval_remove_func, 1, fixup_location_12, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02050         {MODULE_NAME"_remove", eval_remove_func, 2, fixup_location_12, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02051         {MODULE_NAME"_clear", eval_clear_func, 1, fixup_int_12, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02052 
02053         {MODULE_NAME"_oper", eval_stack_func_func, 2, eval_stack_func_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02054         {MODULE_NAME"_oper", eval_stack_func_func, 1, eval_stack_func_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02055 
02056         {MODULE_NAME"_while", eval_while_func, 1, eval_while_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02057         {MODULE_NAME"_while", eval_while_func, 2, eval_while_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02058         {MODULE_NAME"_while_stack", eval_while_stack_func, 1, eval_while_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02059         {MODULE_NAME"_while_stack", eval_while_stack_func, 2, eval_while_fixup, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02060 
02061         {MODULE_NAME"_dump", eval_dump_func, 0, 0, REQUEST_ROUTE | ONREPLY_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE | ONSEND_ROUTE},
02062 
02063         {0, 0, 0, 0, 0}
02064 };
02065 
02066 /*
02067  * Exported parameters
02068  */
02069 static param_export_t params[] = {
02070         {"declare_register", PARAM_STRING|PARAM_USE_FUNC, (void*) declare_register},
02071         {"xlbuf_size",       PARAM_INT, &xlbuf_size},
02072         {0, 0, 0}
02073 };
02074 
02075 
02076 struct module_exports exports = {
02077         MODULE_NAME,
02078         cmds,        /* Exported commands */
02079         0,           /* RPC */
02080         params,      /* Exported parameters */
02081         mod_init,    /* module initialization function */
02082         0,           /* response function*/
02083         destroy_mod, /* destroy function */
02084         0,           /* oncancel function */
02085         child_init   /* per-child init function */
02086 };