Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

config.c

Go to the documentation of this file.
00001 /*! \file config.c
00002           Configuration parser interface.
00003  */
00004 
00005 #include <stdio.h>
00006 #include <errno.h>
00007 #include <string.h>
00008 #include <dlfcn.h>
00009 #include "chtbl.h"
00010 
00011 #define PRIVATE_CODE_ONLY
00012 #include "config.h"
00013 #undef PRIVATE_CODE_ONLY
00014 
00015 /*! \brief Number of characters for the buffer used to store the last error message.
00016  */
00017 
00018 #define CONFIG_H_ERROR_SIZE 2048
00019 
00020 /*! \brief Buffer that contains the last error message.
00021  */
00022 
00023 static char last_error[CONFIG_H_ERROR_SIZE];
00024 
00025 /*! \brief Return the last error message.
00026     \author Denis BEURIVE
00027     \return The function returns a zero terminated, statically allocated, string of characters that represents the last
00028             error message.
00029  */
00030 
00031 char* conf_get_last_error() { return last_error; }
00032 
00033 /*! \brief This flag indicates wether the memory allocated for the hash table is freed or not.
00034  */
00035 
00036 static int allochtab = 0;
00037 
00038 /*! \brief Hash function used by the hash table module.
00039     \author Denis BEURIVE
00040     \remark See example for the hash table module.
00041  */
00042 
00043 int config_hash_function (const void *key)
00044 {
00045   struct user_data *data;
00046   int              index, i;
00047 
00048   data = (struct user_data*)key;
00049   index = 0;
00050 
00051   for (i=0; i<strlen(data->tag); i++) { index *= (int)(data->tag[i]); }
00052 
00053   if (index < 0) { index *= - 1; }
00054 
00055   return index;
00056 }
00057 
00058 /*! \brief Function used to free allocated memory in the hash table.
00059     \author Denis BEURIVE
00060     \remark See example for the hash table module.
00061  */
00062 
00063 void config_free_user_data (void *d)
00064 {
00065   struct user_data *data;
00066 
00067   data = (struct user_data*)d;
00068   free (data->tag);
00069   free (data->value);
00070   free (data);
00071 
00072   return;
00073 }
00074 
00075 /*! \brief Function used to compare 2 elements in the hash table.
00076     \author Denis BEURIVE
00077     \remark See example for the hash table module.
00078  */
00079 
00080 int config_compare_user_data (const void *d1, const void *d2)
00081 {
00082   struct user_data *data1, *data2;
00083 
00084   data1 = (struct user_data*)d1;
00085   data2 = (struct user_data*)d2;
00086 
00087   return !strcmp(data1->tag, data2->tag);
00088 }
00089 
00090 /*! \brief Handler to the hash table.
00091  */
00092 
00093 CHTbl htab;
00094 
00095 /*! \brief This array contains the modems' configuration.
00096            The first record is associated with the default configuration.
00097  */
00098 
00099 struct modem_conf_struct modem_configuration_list[MODEM_CONF_MAX_ENTRY];
00100 
00101 /*! \brief Number of configured modems. This integer represents the number of records in the array
00102            "modem_configuration_list".
00103  */
00104 
00105 int nb_modem;
00106 
00107 /*! \brief Return the number of records in the modems' configuration file.
00108     \author Denis BEURIVE
00109     \return The function returns the number of modems' configuration records.
00110  */
00111 
00112 int get_number_of_modem_conf() { return nb_modem; } 
00113 
00114 /*! \brief Dummy MAC address calculator.
00115     \author Denis BEURIVE
00116     \param addr Pointer to a zero terminated string of characters that represents the original MAC address.
00117     \return The function returns a pointer to a zero terminated, statically allocated, string of characters. This
00118             string contains a copy of the original MAC address.
00119     \remark Make sure that the buffer "mac" is big enough.
00120  */
00121 
00122 char* dummy_mac_processor (char* addr)
00123 {
00124   static char mac[128];
00125 
00126   memset((void*)mac, 0, 128);
00127   strncpy (mac, addr, 127);
00128   return mac;
00129 }
00130 
00131 /*! \brief Flex generated parser.
00132  */
00133 
00134 extern int configlex();
00135 
00136 /*! \brief Flex input file descriptor.
00137  */
00138 
00139 extern FILE *configin;
00140 
00141 /*! \brief Load a given configuration file.
00142     \author Denis BEURIVE
00143     \param path Path to the configuration file to load.
00144     \param err Pointer to an integer that will be used to store the value of 'errno' if an error occured.
00145     \return Upon successful completion, the function returns tha value PARSE_CONFIGURATION_OK.
00146             Otherwise the function may return one of the following values:
00147             <UL>
00148                <LI>PARSE_CONFIGURATION_NO_MEM: Could not allocate memory.
00149                <LI>PARSE_CONFIGURATION_FILE_NOT_FOUND: Could not open configuration file. "errno' is set. 
00150                <LI>PARSE_CONFIGURATION_SYNTAX_ERROR: Syntax error in configuration file.
00151                <LI>PARSE_CONFIGURATION_DUPLICATED_TAG: Configuration contains a duplicated tag.
00152                <LI>PARSE_CONFIGURATION_DLL_OPEN_ERROR: Could not load DLL.
00153                <LI>PARSE_CONFIGURATION_DLL_INVALID: DLL is not valid.
00154                <LI>PARSE_CONFIGURATION_MODEM_CONF_NOT_VALID: Modem's configuration record is not valid.
00155                <LI>PARSE_CONFIGURATION_OK: Success.
00156             </UL>
00157     \warning <UL>
00158                <LI>If the returned value is PARSE_CONFIGURATION_NO_MEM, the module does not free
00159                    allocated memory. You should abort the program.
00160                <LI>If the returned value is PARSE_CONFIGURATION_FILE_NOT_FOUND, PARSE_CONFIGURATION_SYNTAX_ERROR,
00161                    PARSE_CONFIGURATION_DUPLICATED_TAG, PARSE_CONFIGURATION_DLL_OPEN_ERROR,
00162                    PARSE_CONFIGURATION_DLL_INVALID, PARSE_CONFIGURATION_MODEM_CONF_NOT_VALID, 
00163                    the module free all allocated memory.
00164              </UL>
00165     \remark In case you think that the same DLL is loaded multiple times, consider this:
00166             Only a single copy of an shared library file is brought into the address space, even if dlopen is
00167             invoked multiple times in reference to the file, and even if different pathnames are used to reference
00168             the file. 
00169  */
00170 
00171 int parse_configuration_file (char *path, int *err)
00172 {
00173   int rc, i;
00174 
00175   *err   = 0;
00176 
00177   memset((void*)last_error, 0, CONFIG_H_ERROR_SIZE);
00178 
00179   memset ((void*)&modem_configuration_list, 0, sizeof(struct modem_conf_struct)*MODEM_CONF_MAX_ENTRY);
00180 
00181   modem_configuration_list[0].id = 0;
00182   strncpy (modem_configuration_list[0].identifier, "XXXXXX",   MODEM_CONF_IDENTIFIER_SIZE-1);
00183   strncpy (modem_configuration_list[0].tag_name,   "UNKNOWN",  MODEM_CONF_TAG_NAME_SIZE-1);
00184   strncpy (modem_configuration_list[0].autoconf,   "no",       MODEM_CONF_AUTOCONF_SIZE-1);
00185   strncpy (modem_configuration_list[0].action,     "dummy",    MODEM_CONF_ACTION_SIZE-1);
00186   modem_configuration_list[0].dll = NULL;
00187   modem_configuration_list[0].calculate_mac_address = dummy_mac_processor;
00188 
00189   nb_modem = 1;
00190 
00191   /* ------------------------------------------------ */
00192   /* Initialize the hash table                        */
00193   /* ------------------------------------------------ */
00194 
00195   if (
00196        chtbl_init (
00197                     &htab,
00198                     10,
00199                     config_hash_function,
00200                     config_compare_user_data,
00201                     config_free_user_data
00202                   ) == -1
00203      )
00204   { return PARSE_CONFIGURATION_NO_MEM; }
00205 
00206   allochtab = 1;
00207  
00208   /* ------------------------------------------------ */
00209   /* Parse configuration file                         */
00210   /* ------------------------------------------------ */
00211 
00212   configin = fopen (path, "r");
00213   if (configin == NULL) { *err = errno; return PARSE_CONFIGURATION_FILE_NOT_FOUND; }
00214 
00215   rc = configlex();
00216   switch (rc)
00217   {
00218     case CONF_PARSER_SYNTAX_ERROR:        free_all_configuration_data();
00219                                           fclose (configin);
00220                                           return PARSE_CONFIGURATION_SYNTAX_ERROR; 
00221     case CONF_PARSER_DUPLICATED_TAG: free_all_configuration_data();
00222                                           fclose (configin);
00223                                           return PARSE_CONFIGURATION_DUPLICATED_TAG;
00224     case CONF_PARSER_NO_MEM:              fclose (configin);
00225                                           return PARSE_CONFIGURATION_NO_MEM;
00226     case CONF_PARSER_IDENTIFIER_TOO_LONG: free_all_configuration_data();
00227                                           fclose (configin);
00228                                           return PARSE_CONFIGURATION_MODEM_CONF_NOT_VALID;
00229     case CONF_PARSER_TAG_NAME_TOO_LONG:   free_all_configuration_data();
00230                                           fclose (configin);
00231                                           return PARSE_CONFIGURATION_MODEM_CONF_NOT_VALID;
00232     case CONF_PARSER_AUTOCONF_TOO_LONG:   free_all_configuration_data();
00233                                           fclose (configin);
00234                                           return PARSE_CONFIGURATION_MODEM_CONF_NOT_VALID;
00235     case CONF_PARSER_ACTION_TOO_LONG:     free_all_configuration_data();
00236                                           fclose (configin);
00237                                           return PARSE_CONFIGURATION_MODEM_CONF_NOT_VALID;
00238     case CONF_PARSER_TOO_MANY_ENTRIES:    free_all_configuration_data();
00239                                           fclose (configin);
00240                                           return PARSE_CONFIGURATION_MODEM_CONF_NOT_VALID;
00241   }
00242 
00243   fclose (configin);
00244 
00245   /* ------------------------------------------------ */
00246   /* Load all plugins                                 */
00247   /* ------------------------------------------------ */
00248 
00249   for (i=1; i<get_number_of_modem_conf(); i++)
00250   {
00251     if (strcasecmp(modem_configuration_list[i].action, "dummy") == 0)
00252     { modem_configuration_list[i].calculate_mac_address = dummy_mac_processor; }
00253     else {
00254            modem_configuration_list[i].dll = dlopen (modem_configuration_list[i].action, RTLD_LAZY);
00255            if (modem_configuration_list[i].dll == NULL)
00256            {
00257              if (dlerror() != NULL) { strncpy (last_error, dlerror(), CONFIG_H_ERROR_SIZE-1); }
00258              free_all_configuration_data();
00259              return PARSE_CONFIGURATION_DLL_OPEN_ERROR;
00260            }
00261 
00262            modem_configuration_list[i].calculate_mac_address = dlsym (modem_configuration_list[i].dll, "calculate_mac");
00263            if (dlerror() != NULL) {
00264                                     strncpy (last_error, dlerror(), CONFIG_H_ERROR_SIZE-1);
00265                                     free_all_configuration_data();
00266                                     return PARSE_CONFIGURATION_DLL_INVALID;
00267                                   }
00268          }
00269 
00270   }
00271 
00272   return PARSE_CONFIGURATION_OK;
00273 }
00274 
00275 /*! \brief Returns the ID of a given MAC address.
00276     \author Denis BEURIVE
00277     \param mac Pointer to a zero terminated string of characters that represents the modem's MAC address.
00278     \return The function returns a integer that represents the modem's ID.
00279  */
00280 
00281 int modem_conf_get_id (char *mac)
00282 {
00283   int i;
00284 
00285   for (i=0; i<get_number_of_modem_conf(); i++)
00286   { if (strncmp(modem_configuration_list[i].identifier, mac, 6) == 0) { return i; } }
00287 
00288   return 0;
00289 }
00290 
00291 /*! \brief Returns the tag name of a given MAC address, representd by its ID.
00292     \author Denis BEURIVE
00293     \param id ID of the MAC address (as returned by the function modem_conf_get_id()).
00294     \return The function returns a pointer to a zero terminated string of characters that represents the tag name.
00295  */
00296 
00297 char* modem_conf_get_tag_name (int id) { return modem_configuration_list[id].tag_name; }
00298 
00299 /*! \brief Returns a value that indicates if a given modem supports auto-configuration.
00300     \author Denis BEURIVE
00301     \param id ID of the MAC address (as returned by the function modem_conf_get_id()).
00302     \return The function returns one of the following values:
00303             <UL>
00304                 <li>1: The modem supports auto-configuration.
00305                 <li>0: The modem does not support auto-configuration.
00306             </UL>
00307  */
00308 
00309 int modem_conf_is_autoconf (int id)
00310 {
00311   if (strcasecmp (modem_configuration_list[id].autoconf, "yes") == 0) { return 1; }
00312   return 0;
00313 }
00314 
00315 /*! \brief Returns the MAC processor for a given MAC address.
00316     \author Denis BEURIVE
00317     \param id ID of the MAC address (as returned by the function modem_conf_get_id()).
00318     \return The function returns a pointer to a function used to calculate the new MAC address.
00319  */
00320 
00321 void* modem_conf_get_function (int id)
00322 {
00323   return modem_configuration_list[id].calculate_mac_address;
00324 }
00325 
00326 /*! \brief Free all data allocated for the hash table.
00327     \author Denis BEURIVE
00328  */
00329 
00330 void free_all_configuration_data() { if (allochtab == 1) { chtbl_destroy (&htab); allochtab = 0; } }
00331 
00332 /*! \brief Return the value associated with a given tag.
00333     \author Denis BEURIVE
00334     \param tag Pointer to a zero terminated string of characters that represents the tag to look for.
00335     \param value Pointer that will point to the corresponding value (if the tag was found).
00336     \return <UL>
00337               <LI>If the tag could not be find, the function returns the value 0. 'value' is NULL.
00338               <LI>If the tag has been found, the function returns the value 1.
00339               <LI>If the function ran out of memory, the function returns the value -1. 'value' is NULL.
00340             </UL> 
00341  */
00342 
00343 int get_value (char *tag, char **value)
00344 {
00345   struct user_data *ud, sud;
00346   int              cr, retval;
00347 
00348   /* ------------------------------------------------ */
00349   /* Initialise values                                */
00350   /* ------------------------------------------------ */
00351 
00352   *value  = NULL;
00353   retval  = 0;
00354  
00355   /* ------------------------------------------------ */
00356   /* Prepare user data for lookup                     */
00357   /* ------------------------------------------------ */
00358 
00359   sud.tag   = tag;
00360   sud.value = NULL;
00361 
00362   ud = &sud;
00363 
00364   /* ------------------------------------------------ */
00365   /* Lookup hash table                                */
00366   /* ------------------------------------------------ */
00367 
00368   cr = chtbl_lookup (&htab, (void**)&ud);
00369 
00370   if (cr == 0) { retval = 1; *value = ud->value; }
00371 
00372   return retval;
00373 }
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 

Generated on Mon Jun 19 12:31:05 2006 for MyDhcp_V2 by doxygen1.2.15