parse_config.c

Go to the documentation of this file.
00001 /*
00002  * $Id: parse_config.c 4518 2008-07-28 15:39:28Z henningw $
00003  *
00004  * PERMISSIONS module
00005  *
00006  * Copyright (C) 2003 Miklós Tirpák (mtirpak@sztaki.hu)
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  */
00025 
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <ctype.h>
00029 #include "../../sr_module.h"
00030 #include "rule.h"
00031 #include "parse_config.h"
00032 
00033 
00034 /*
00035  * parse a comma separated expression list like a, b, c
00036  * return 0 on success, -1 on error
00037  * parsed expressions are returned in **e
00038  */
00039 static int parse_expression_list(char *str, expression **e) 
00040 {
00041    int start=0, i=-1, j=-1, apost=0;
00042    char str2[EXPRESSION_LENGTH];
00043    expression *e1=NULL, *e2;
00044    
00045    if (!str || !e) return -1;
00046 
00047    *e = NULL;
00048    do {
00049       i++;
00050       switch(str[i]) {
00051          case '"':   apost = !apost;
00052                break;
00053          case ',':   if (apost) break;
00054          case '\0':  /* word found */
00055                while ((str[start] == ' ') || (str[start] == '\t')) start++;
00056                if (str[start] == '"') start++;
00057                j = i-1;
00058                while ((0 < j) && ((str[j] == ' ') || (str[j] == '\t'))) j--;
00059                if ((0 < j) && (str[j] == '"')) j--;
00060                if (start<=j) {
00061                   /* valid word */
00062                   if (j-start+1+1>EXPRESSION_LENGTH) {
00063                      LM_ERR("expression too long "
00064                         "<%.*s>(%d)\n",j-start+1,str+start,j-start+1);
00065                      goto error;
00066                   }
00067                   strncpy(str2, str+start, j-start+1);
00068                   str2[j-start+1] = '\0';
00069                   
00070                   e2 = new_expression(str2);
00071                   if (!e2)
00072                      /* memory error */
00073                      goto error;
00074                   
00075                   if (e1) {
00076                      /* it is not the first */
00077                      e1->next = e2;
00078                      e1 = e2;
00079                   } else {
00080                      /* it is the first */
00081                      *e = e1 = e2;
00082                   }
00083                } else {
00084                   /* parsing error */
00085                   goto error;
00086                }
00087                /* for the next word */
00088                start = i+1;
00089       }
00090    } while (str[i] != '\0');
00091 
00092    return 0;
00093 error:
00094    if (*e) {
00095       free_expression(*e);
00096       *e = NULL;
00097    }
00098    return -1;
00099 }
00100 
00101 
00102 /*
00103  * parse a complex expression list like a, b, c EXCEPT d, e
00104  * return 0 on success, -1 on error
00105  * parsed expressions are returned in **e, and exceptions are returned in **e_exceptions
00106  */
00107 static int parse_expression(char *str, expression **e, expression **e_exceptions) 
00108 {
00109    char *except, str2[LINE_LENGTH+1];
00110    int  i,j;
00111 
00112    if (!str || !e || !e_exceptions) return -1;
00113 
00114    except = strstr(str, " EXCEPT ");
00115    if (except) {
00116       /* exception found */
00117       strncpy(str2, str, except-str);
00118       str2[except-str] = '\0';
00119       /* except+8 points to the exception */
00120       if (parse_expression_list(except+8, e_exceptions)) {
00121          /* error */
00122          *e = *e_exceptions = NULL;
00123          return -1;
00124       }
00125    } else {
00126       /* no exception */
00127       strcpy(str2, str);
00128       *e_exceptions = NULL;
00129    }
00130 
00131    for( i=0; isspace((int)str2[i]) ; i++);
00132    for( j=strlen(str2)-1 ; isspace((int)str2[j]) ; str2[j--]=0);
00133 
00134    if (strcmp("ALL", str2+i) == 0) {
00135       *e = NULL;
00136    } else {
00137       if (parse_expression_list(str2+i, e)) {
00138          /* error */
00139          if (*e_exceptions) free_expression(*e_exceptions);
00140          *e = *e_exceptions = NULL;
00141          return -1;
00142       }
00143    }
00144    return 0;
00145 }
00146 
00147 
00148 /*
00149  * parse one line of the config file
00150  * return the rule according to line
00151  */
00152 static rule *parse_config_line(char *line) 
00153 {
00154    rule  *rule1;
00155    expression *left, *left_exceptions, *right, *right_exceptions;
00156    int   i=-1, exit=0, apost=0, colon=-1, eval=0;
00157    static char str1[LINE_LENGTH], str2[LINE_LENGTH+1];
00158 
00159    if (!line) return 0;
00160 
00161    rule1 = 0;
00162    left = left_exceptions = right = right_exceptions = 0;
00163 
00164    while (!exit) {
00165       i++;
00166       switch(line[i]) {
00167          case '"':   apost = !apost;
00168                eval = 1;
00169                break;
00170          
00171          case ':':   if (!apost) colon = i;
00172                eval = 1;
00173                break;
00174          
00175          case '#':   if (apost) break;       
00176          case '\0':
00177          case '\n':
00178                exit = 1;
00179                break;
00180          case ' ':   break;
00181          case '\t':  break;
00182             
00183          default: eval = 1;
00184          
00185       }
00186    }
00187 
00188    if (eval) {
00189       if ((0<colon) && (colon+1<i)) {
00190          /* valid line */
00191          
00192          /* left expression */
00193          strncpy(str1, line, colon);
00194          str1[colon] = '\0';
00195          if (parse_expression(str1, &left, &left_exceptions)) {
00196             /* error */
00197             LM_ERR("failed to parse line-left: %s\n", line);
00198             goto error;
00199          }
00200          
00201          /* right expression */
00202          strncpy(str2, line+colon+1, i-colon-1);
00203          str2[i-colon-1] = '\0';
00204          if (parse_expression(str2, &right, &right_exceptions)) {
00205             /* error */
00206             LM_ERR("failed to parse line-right: %s\n", line);
00207             goto error;
00208          }
00209          
00210          rule1 = new_rule();
00211          if (!rule1) {
00212             LM_ERR("can't create new rule\n");
00213             goto error;
00214          }
00215 
00216          rule1->left = left;
00217          rule1->left_exceptions = left_exceptions;
00218          rule1->right = right;
00219          rule1->right_exceptions = right_exceptions;
00220          return rule1;
00221       } else {
00222          /* error */
00223          LM_ERR("failed to parse line: %s\n", line);
00224       }
00225    }
00226    return 0;
00227 
00228  error:
00229    if (left) free_expression(left);
00230    if (left_exceptions) free_expression(left_exceptions);
00231 
00232    if (right) free_expression(right);
00233    if (right_exceptions) free_expression(right_exceptions);
00234    
00235    return 0;
00236 }
00237 
00238 
00239 /*
00240  * parse a config file
00241  * return a list of rules
00242  */
00243 rule *parse_config_file(char *filename) 
00244 {
00245    FILE  *file;
00246    char  line[LINE_LENGTH+1];
00247    rule  *start_rule = NULL, *rule1 = NULL, *rule2 = NULL;
00248 
00249    file = fopen(filename,"r");
00250    if (!file) {
00251       LM_WARN("file not found: %s\n", filename);
00252       return NULL;
00253    }
00254    
00255    while (fgets(line, LINE_LENGTH, file)) {
00256       rule2 = parse_config_line(line);
00257       if (rule2) {
00258          if (rule1) {
00259             /* it is not the first rule */
00260             rule1->next = rule2;
00261          } else {
00262             /* it is the first rule */
00263             start_rule = rule2;
00264          }
00265          rule1 = rule2;
00266       }
00267    }
00268    
00269    fclose(file);
00270    return start_rule;   /* returns the linked list */
00271 }

Generated on Thu May 24 00:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6