/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.1 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /*! \file common/config/config_load_configmodule.c * \brief configuration module, load the shared library implementing the configuration module * \author Francois TABURET * \date 2017 * \version 0.1 * \company NOKIA BellLabs France * \email: francois.taburet@nokia-bell-labs.com * \note * \warning */ #define _GNU_SOURCE #include #include #include #include #include #include #include "common/platform_types.h" #define CONFIG_LOADCONFIG_MAIN #include "config_load_configmodule.h" #include "config_userapi.h" #include "../utils/LOG/log.h" #define CONFIG_SHAREDLIBFORMAT "libparams_%s.so" #include "nfapi/oai_integration/vendor_ext.h" #include "config_common.h" // clang-format off static char config_helpstr [] = "\n lte-softmodem -O [config mode]<:dbgl[debugflags]><:incp[path]>\n \ debugflags can also be defined in the config section of the config file\n \ debugflags: mask, 1->print parameters, 2->print memory allocations debug messages\n \ 4->print command line processing debug messages\n \ incp parameter can be used to define the include path used for config files (@include directive)\n \ defaults is set to the path of the main config file.\n"; static paramdef_t Config_Params[] = { /*--------------------------------------------------------------------------------------------------------------------------*/ /* config parameters for config module */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*--------------------------------------------------------------------------------------------------------------------------*/ {CONFIGP_DEBUGFLAGS, config_helpstr, 0, .uptr = NULL, .defintval = 0, TYPE_MASK, 0}, {CONFIGP_TMPDIR, CONFIG_HELP_TMPDIR, PARAMFLAG_NOFREE, .strptr = NULL, .defstrval = "/tmp", TYPE_STRING, 0}, }; // clang-format on int load_config_sharedlib(configmodule_interface_t *cfgptr) { void *lib_handle; char fname[128]; char libname[FILENAME_MAX]; int st; st=0; sprintf(libname,CONFIG_SHAREDLIBFORMAT,cfgptr->cfgmode); lib_handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE); if (!lib_handle) { fprintf(stderr,"[CONFIG] %s %d Error calling dlopen(%s): %s\n",__FILE__, __LINE__, libname,dlerror()); st = -1; } else { sprintf (fname,"config_%s_init",cfgptr->cfgmode); cfgptr->init = dlsym(lib_handle,fname); if (cfgptr->init == NULL ) { printf("[CONFIG] %s %d no function %s for config mode %s\n", __FILE__, __LINE__,fname, cfgptr->cfgmode); } else { st = cfgptr->init(cfgptr); printf("[CONFIG] function %s returned %i\n", fname, st); } sprintf (fname,"config_%s_get",cfgptr->cfgmode); cfgptr->get = dlsym(lib_handle,fname); if (cfgptr->get == NULL ) { printf("[CONFIG] %s %d no function %s for config mode %s\n", __FILE__, __LINE__,fname, cfgptr->cfgmode); st = -1; } sprintf (fname,"config_%s_getlist",cfgptr->cfgmode); cfgptr->getlist = dlsym(lib_handle,fname); if (cfgptr->getlist == NULL ) { printf("[CONFIG] %s %d no function %s for config mode %s\n", __FILE__, __LINE__,fname, cfgptr->cfgmode); st = -1; } if (cfgptr->rtflags & CONFIG_SAVERUNCFG) { sprintf(fname, "config_%s_set", cfgptr->cfgmode); cfgptr->set = dlsym(lib_handle, fname); if (cfgptr->set == NULL) { printf("[CONFIG] %s %d no function %s for config mode %s\n", __FILE__, __LINE__, fname, cfgptr->cfgmode); st = -1; } sprintf(fname, "config_%s_write_parsedcfg", cfgptr->cfgmode); cfgptr->write_parsedcfg = dlsym(lib_handle, fname); if (cfgptr->write_parsedcfg == NULL) { printf("[CONFIG] %s %d no function %s for config mode %s\n", __FILE__, __LINE__, fname, cfgptr->cfgmode); } } sprintf (fname,"config_%s_end",cfgptr->cfgmode); cfgptr->end = dlsym(lib_handle,fname); if (cfgptr->end == NULL) { printf("[CONFIG] %s %d no function %s for config mode %s\n", __FILE__, __LINE__,fname, cfgptr->cfgmode); } } return st; } /*-----------------------------------------------------------------------------------*/ /* from here: interface implementtion of the configuration module */ int nooptfunc(void) { return 0; }; int config_cmdlineonly_getlist(configmodule_interface_t *cfg, paramlist_def_t *ParamList, paramdef_t *params, int numparams, char *prefix) { ParamList->numelt = 0; return 0; } int config_cmdlineonly_get(configmodule_interface_t *cfg, paramdef_t *cfgoptions, int numoptions, char *prefix) { int defval; int fatalerror=0; int numdefvals=0; for(int i=0; i option, default cfgmode to libconfig with one parameter, the path to the configuration file cfgmode must not be NULL */ modeparams=cfgmode; cfgmode=strdup(CONFIG_LIBCONFIGFILE); } static configmodule_interface_t *cfgptr; if (cfgptr) printf("ERROR: Call load_configmodule more than one time\n"); // The macros are not thread safe print_params and similar cfgptr = calloc(sizeof(configmodule_interface_t), 1); /* argv_info is used to memorize command line options which have been recognized */ /* and to detect unrecognized command line options which might have been specified */ cfgptr->argv_info = calloc(sizeof(int32_t), argc+10); /* argv[0] is the exec name, always Ok */ cfgptr->argv_info[0] |= CONFIG_CMDLINEOPT_PROCESSED; /* When reuested _(_--OW or rtflag is 5), a file with config parameters, as defined after all processing, will be created */ if (OWoptIdx >= 0) { cfgptr->argv_info[OWoptIdx] |= CONFIG_CMDLINEOPT_PROCESSED; cfgptr->rtflags |= CONFIG_SAVERUNCFG; } /* when OoptIdx is >0, -O option has been detected at position OoptIdx * we must memorize arv[OoptIdx is Ok */ if (OoptIdx >= 0) { cfgptr->argv_info[OoptIdx] |= CONFIG_CMDLINEOPT_PROCESSED; cfgptr->argv_info[OoptIdx+1] |= CONFIG_CMDLINEOPT_PROCESSED; } cfgptr->rtflags = cfgptr->rtflags | tmpflags; cfgptr->argc = argc; cfgptr->argv = argv; cfgptr->cfgmode=strdup(cfgmode); cfgptr->num_cfgP=0; atoken=strtok_r(modeparams,":",&strtokctx); while ( cfgptr->num_cfgP< CONFIG_MAX_OOPT_PARAMS && atoken != NULL) { /* look for debug level in the config parameters, it is common to all config mode and will be removed from the parameter array passed to the shared module */ char *aptr; aptr=strcasestr(atoken,"dbgl"); if (aptr != NULL) { cfgptr->rtflags = cfgptr->rtflags | strtol(aptr+4,NULL,0); } else { cfgptr->cfgP[cfgptr->num_cfgP] = strdup(atoken); cfgptr->num_cfgP++; } atoken = strtok_r(NULL,":",&strtokctx); } for (i = 0; i < cfgptr->num_cfgP; i++) { /* check if that file actually exists */ if (access(cfgptr->cfgP[i], F_OK) != 0) { fprintf(stderr, "error: file %s does not exist\n", cfgptr->cfgP[i]); for (int j = 0; j < cfgptr->num_cfgP; ++j) free(cfgptr->cfgP[j]); free(modeparams); free(cfgptr->cfgmode); free(cfgptr->argv_info); free(cfgptr); if (cfgmode != NULL) free(cfgmode); return NULL; } } if (cfgptr->rtflags & CONFIG_PRINTPARAMS) { cfgptr->status = malloc(sizeof(configmodule_status_t)); } if (strstr(cfgparam,CONFIG_CMDLINEONLY) == NULL) { i=load_config_sharedlib(cfgptr); if (i == 0) { printf("[CONFIG] config module %s loaded\n",cfgmode); int idx = config_paramidx_fromname(Config_Params, sizeofArray(Config_Params), CONFIGP_DEBUGFLAGS); Config_Params[idx].uptr = &(cfgptr->rtflags); idx = config_paramidx_fromname(Config_Params, sizeofArray(Config_Params), CONFIGP_TMPDIR); Config_Params[idx].strptr = &(cfgptr->tmpdir); config_get(cfgptr, Config_Params, sizeofArray(Config_Params), CONFIG_SECTIONNAME); } else { fprintf(stderr,"[CONFIG] %s %d config module \"%s\" couldn't be loaded\n", __FILE__, __LINE__,cfgmode); cfgptr->rtflags = cfgptr->rtflags | CONFIG_HELP | CONFIG_ABORT; } } else { cfgptr->init = (configmodule_initfunc_t)nooptfunc; cfgptr->get = config_cmdlineonly_get; cfgptr->getlist = config_cmdlineonly_getlist; cfgptr->end = (configmodule_endfunc_t)nooptfunc; } printf("[CONFIG] debug flags: 0x%08x\n", cfgptr->rtflags); if (modeparams != NULL) free(modeparams); if (cfgmode != NULL) free(cfgmode); if (CONFIG_ISFLAGSET(CONFIG_ABORT)) { config_printhelp(Config_Params, sizeofArray(Config_Params), CONFIG_SECTIONNAME); // exit(-1); } return cfgptr; } /* Possibly write config file, with parameters which have been read and after command line parsing */ void write_parsedcfg(configmodule_interface_t *cfgptr) { if (cfgptr->status && (cfgptr->rtflags & CONFIG_SAVERUNCFG)) { printf_params(cfgptr, "[CONFIG] Runtime params creation status: %i null values, %i errors, %i empty list or array, %i successfull \n", cfgptr->status->num_err_nullvalue, cfgptr->status->num_err_write, cfgptr->status->emptyla, cfgptr->status->num_write); } if (cfgptr->write_parsedcfg != NULL) { printf("[CONFIG] calling config module write_parsedcfg function...\n"); cfgptr->write_parsedcfg(cfgptr); } } /* free memory allocated when reading parameters */ /* config module could be initialized again after this call */ void end_configmodule(configmodule_interface_t *cfgptr) { if (cfgptr != NULL) { write_parsedcfg(cfgptr); if (cfgptr->end != NULL) { printf ("[CONFIG] calling config module end function...\n"); cfgptr->end(cfgptr); } pthread_mutex_lock(&cfgptr->memBlocks_mutex); printf ("[CONFIG] free %u config value pointers\n",cfgptr->numptrs); for(int i=0; inumptrs ; i++) { if (cfgptr->oneBlock[i].ptrs != NULL && cfgptr->oneBlock[i].ptrsAllocated== true && cfgptr->oneBlock[i].toFree) { free(cfgptr->oneBlock[i].ptrs); memset(&cfgptr->oneBlock[i], 0, sizeof(cfgptr->oneBlock[i])); } } cfgptr->numptrs=0; pthread_mutex_unlock(&cfgptr->memBlocks_mutex); if (cfgptr->cfgmode) free(cfgptr->cfgmode); if (cfgptr->argv_info) free(cfgptr->argv_info); free(cfgptr); } }