Navigation


Changeset 925:e5a09fab5ef3 in freeDiameter


Ignore:
Timestamp:
Mar 2, 2013, 10:03:04 PM (11 years ago)
Author:
Sebastien Decugis <sdecugis@freediameter.net>
Branch:
default
Phase:
public
Message:

Add support for 'include' in freeDiameter configuration file

Files:
2 edited

Legend:

Unmodified
Added
Removed
  • doc/freediameter.conf.sample

    r873 r925  
    22
    33# Only the "TLS_Cred" directive is really mandatory in this file.
     4
     5# It is possible to use "include" keyword to import additional files
     6# e.g.: include "/etc/freeDiameter.d/*.conf"
     7
    48
    59##############################################################
  • libfdcore/fdd.l

    r918 r925  
    6767/* %option noinput ? */
    6868#define YY_NO_INPUT
     69
     70/* Additional for files inclusion */
     71#include <glob.h>
     72#include <string.h>
     73
     74#define MAX_NESTED_CONF_FILES   5
     75
     76struct nested_conffiles_t {
     77        YY_BUFFER_STATE parent_level_state;
     78        glob_t filelist;
     79        int current_file;
     80} nested_conffiles[MAX_NESTED_CONF_FILES];
     81
     82int current_nested_level = 0;
     83
     84int globerrfct(const char *epath, int eerrno)
     85{
     86        TRACE_DEBUG_ERROR("Failed to scan %s: %s\n", epath, strerror(eerrno));
     87        return 1;
     88}
     89
    6990%}
    7091
     
    7394%option nounput
    7495
     96%x in_include
     97
    7598/* Quoted string. Multilines do not match. */
    7699qstring         \"[^\"\n]*\"
    77100
    78101%%
    79 
    80102<*>\n                   {
    81103                                /* Update the line count */
     
    87109<*>([[:space:]]{-}[\n])+        ; /* Eat all spaces, not new lines */
    88110<*>#.*$                 ; /* Eat all comments */
     111
     112
     113include         BEGIN(in_include);
     114        /* Following an "include" keyword */
     115<in_include>{
     116{qstring}       { /* Name of the file to include. This is directly sent to glob. */
     117                        int globerror=0;
     118                        char * buf = strdup(yytext+1);
     119                        if (buf[yyleng-2] != '"')
     120                        {
     121                                TRACE_DEBUG_ERROR("Unterminated string: %s\n", yytext);
     122                                return LEX_ERROR;
     123                        }
     124                        buf[yyleng-2] = '\0';
     125
     126                        if (current_nested_level >= MAX_NESTED_CONF_FILES)
     127                        {
     128                                TRACE_DEBUG_ERROR("Too many recursion levels in configuration files includes\n");
     129                                return LEX_ERROR;
     130                        }
     131
     132                        /* glob the include */
     133                        globerror = glob(buf, GLOB_ERR, globerrfct, &nested_conffiles[current_nested_level].filelist);
     134
     135                        if (globerror == GLOB_NOSPACE)
     136                        {
     137                                TRACE_DEBUG_ERROR("Not enough memory to parse include directive.\n");
     138                                return LEX_ERROR;
     139                        }
     140                        if (globerror == GLOB_ABORTED)
     141                        {
     142                                TRACE_DEBUG_ERROR("An error was encountered in include directive.\n");
     143                                return LEX_ERROR;
     144                        }
     145                        if (globerror == GLOB_NOMATCH)
     146                        {
     147                                globfree(&nested_conffiles[current_nested_level].filelist);
     148                                goto nomatch;
     149                        }
     150                        if (globerror)
     151                        {
     152                                TRACE_DEBUG_ERROR("Unexpected error in glob (%d).\n", globerror);
     153                                return LEX_ERROR;
     154                        }
     155
     156                        /* We have a list of files to include. */
     157
     158                        /* save the current buffer for returning when this include has been parsed */
     159                        nested_conffiles[current_nested_level].parent_level_state = YY_CURRENT_BUFFER;
     160
     161                        /* Start with the first match */
     162                        nested_conffiles[current_nested_level].current_file = 0;
     163
     164                        yyin = fopen( nested_conffiles[current_nested_level].filelist.gl_pathv[0], "r" );
     165
     166                        if ( ! yyin )
     167                        {
     168                                TRACE_DEBUG_ERROR("Error in %s: %s", nested_conffiles[current_nested_level].filelist.gl_pathv[0], strerror(errno));
     169                                return LEX_ERROR;
     170                        }
     171
     172                        yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ));
     173
     174                        /* In case of recursive includes */
     175                        current_nested_level++;
     176
     177nomatch:
     178                        BEGIN(INITIAL);
     179                }
     180}
     181
     182<<EOF>> {
     183                        if (current_nested_level == 0)
     184                        {
     185                              /* We are at the end of parsing */
     186                              yyterminate();
     187                        }
     188
     189                        /* Otherwise we are doing an include statement */
     190                        --current_nested_level;
     191                        yy_delete_buffer(YY_CURRENT_BUFFER);
     192
     193                        /* Go to next file, if any */
     194                        nested_conffiles[current_nested_level].current_file++;
     195                        if ( nested_conffiles[current_nested_level].filelist.gl_pathv[nested_conffiles[current_nested_level].current_file] == NULL )
     196                        {
     197                                /* We have finished with this list of includes */
     198                                globfree(&nested_conffiles[current_nested_level].filelist);
     199                                yy_switch_to_buffer(nested_conffiles[current_nested_level].parent_level_state);
     200                        }
     201                        else
     202                        {
     203                                /* Proceed to next included file */
     204                                yyin = fopen( nested_conffiles[current_nested_level].filelist.gl_pathv[nested_conffiles[current_nested_level].current_file], "r" );
     205
     206                                if ( ! yyin )
     207                                {
     208                                        TRACE_DEBUG_ERROR("Error in %s: %s", nested_conffiles[current_nested_level].filelist.gl_pathv[nested_conffiles[current_nested_level].current_file], strerror(errno));
     209                                        return LEX_ERROR;
     210                                }
     211
     212                                yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ));
     213
     214                                /* In case of recursive includes */
     215                                current_nested_level++;
     216                        }
     217
     218}
    89219
    90220{qstring}               {
Note: See TracChangeset for help on using the changeset viewer.