/* * 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/cmdline/config_libconfig.c * \brief configuration module, command line parsing implementation * \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 <string.h> #include <stdlib.h> #include <stdio.h> #include <ctype.h> #include <errno.h> #include <platform_types.h> #include "config_userapi.h" #include "../utils/LOG/log.h" int parse_stringlist(paramdef_t *cfgoptions, char *val) { char *atoken; char *tokctx; char *tmpval=strdup(val); int numelt=0; cfgoptions->numelt=0; atoken=strtok_r(tmpval, ",",&tokctx); while(atoken != NULL) { numelt++ ; atoken=strtok_r(NULL, ",",&tokctx); } free(tmpval); config_check_valptr(cfgoptions,(char **)&(cfgoptions->strlistptr), sizeof(char *) * numelt); cfgoptions->numelt=numelt; atoken=strtok_r(val, ",",&tokctx); for( int i=0; i<cfgoptions->numelt && atoken != NULL ; i++) { config_check_valptr(cfgoptions,&(cfgoptions->strlistptr[i]),strlen(atoken)+1); sprintf(cfgoptions->strlistptr[i],"%s",atoken); printf_params("[LIBCONFIG] %s[%i]: %s\n", cfgoptions->optname,i,cfgoptions->strlistptr[i]); atoken=strtok_r(NULL, ",",&tokctx); } return (cfgoptions->numelt > 0); } int processoption(paramdef_t *cfgoptions, char *value) { char *tmpval = value; int optisset=0; char defbool[2]="1"; if ( value == NULL) { if( (cfgoptions->paramflags &PARAMFLAG_BOOL) == 0 ) { /* not a boolean, argument required */ CONFIG_PRINTF_ERROR("[CONFIG] command line, option %s requires an argument\n",cfgoptions->optname); } else { /* boolean value option without argument, set value to true*/ tmpval = defbool; } } switch(cfgoptions->type) { char *charptr; case TYPE_STRING: if (cfgoptions->numelt == 0 ) { config_check_valptr(cfgoptions, cfgoptions->strptr, strlen(tmpval)+1); sprintf(*(cfgoptions->strptr), "%s",tmpval); } else { sprintf( (char *)(cfgoptions->strptr), "%s",tmpval); } printf_cmdl("[CONFIG] %s set to %s from command line\n", cfgoptions->optname, tmpval); optisset=1; break; case TYPE_STRINGLIST: optisset=parse_stringlist(cfgoptions,tmpval); break; case TYPE_UINT32: case TYPE_INT32: case TYPE_UINT16: case TYPE_INT16: case TYPE_UINT8: case TYPE_INT8: config_check_valptr(cfgoptions, (char **)&(cfgoptions->iptr),sizeof(int32_t)); config_assign_int(cfgoptions,cfgoptions->optname,(int32_t)strtol(tmpval,&charptr,0)); if( *charptr != 0) { CONFIG_PRINTF_ERROR("[CONFIG] command line, option %s requires an integer argument\n",cfgoptions->optname); } optisset=1; break; case TYPE_UINT64: case TYPE_INT64: config_check_valptr(cfgoptions, (char **)&(cfgoptions->i64ptr),sizeof(uint64_t)); *(cfgoptions->i64ptr)=strtoll(tmpval,&charptr,0); if( *charptr != 0) { CONFIG_PRINTF_ERROR("[CONFIG] command line, option %s requires an integer argument\n",cfgoptions->optname); } printf_cmdl("[CONFIG] %s set to %lli from command line\n", cfgoptions->optname, (long long)*(cfgoptions->i64ptr)); optisset=1; break; case TYPE_UINTARRAY: case TYPE_INTARRAY: break; case TYPE_DOUBLE: config_check_valptr(cfgoptions, (char **)&(cfgoptions->dblptr),sizeof(double)); *(cfgoptions->dblptr) = strtof(tmpval,&charptr); if( *charptr != 0) { CONFIG_PRINTF_ERROR("[CONFIG] command line, option %s requires a double argument\n",cfgoptions->optname); } printf_cmdl("[CONFIG] %s set to %lf from command line\n", cfgoptions->optname, *(cfgoptions->dblptr)); optisset=1; break; case TYPE_IPV4ADDR: break; default: CONFIG_PRINTF_ERROR("[CONFIG] command line, %s type %i not supported\n",cfgoptions->optname, cfgoptions->type); break; } /* switch on param type */ if (optisset == 1) { cfgoptions->paramflags = cfgoptions->paramflags | PARAMFLAG_PARAMSET; } return optisset; } /*--------------------------------------------------------------------*/ /* check unknown options in the command line */ int config_check_unknown_cmdlineopt(char *prefix) { int unknowndetected=0; char testprefix[CONFIG_MAXOPTLENGTH]=""; int finalcheck = 0; if (prefix != NULL) { if (strcmp(prefix,CONFIG_CHECKALLSECTIONS) == 0) finalcheck = 1; else if (strlen(prefix) > 0) { sprintf(testprefix,"--%s.",prefix); } } for (int i=1; i<config_get_if()->argc ; i++) { if ( !finalcheck && strstr(config_get_if()->argv[i],testprefix) == NULL ) continue; if ( !finalcheck && testprefix[0]==0 && index(config_get_if()->argv[i],'.') != NULL) continue; if ( !finalcheck && isdigit(config_get_if()->argv[i][0])) continue; if ( !finalcheck && config_get_if()->argv[i][0] == '-' && isdigit(config_get_if()->argv[i][1])) continue; if ( (config_get_if()->argv_info[i] & CONFIG_CMDLINEOPT_PROCESSED) == 0 ) { fprintf(stderr,"[CONFIG] unknown option: %s\n", config_get_if()->argv[i] ); unknowndetected++; } } if (unknowndetected > 0) { CONFIG_PRINTF_ERROR("[CONFIG] %i unknown option(s) in command line starting with %s (section %s)\n", unknowndetected,testprefix,((prefix==NULL)?"":prefix)); } return unknowndetected; } /* config_check_unknown_cmdlineopt */ int config_process_cmdline(paramdef_t *cfgoptions,int numoptions, char *prefix) { int c = config_get_if()->argc; int i,j; char *pp; char cfgpath[CONFIG_MAXOPTLENGTH]; j = 0; i = 0; while (c > 0 ) { char *oneargv = strdup(config_get_if()->argv[i]); /* we use strtok_r which modifies its string paramater, and we don't want argv to be modified */ /* first check help options, either --help, -h or --help_<section> */ if (strncmp(oneargv, "-h",2) == 0 || strncmp(oneargv, "--help",6) == 0 ) { char *tokctx; pp=strtok_r(oneargv, "_",&tokctx); config_get_if()->argv_info[i] |= CONFIG_CMDLINEOPT_PROCESSED; if (pp == NULL || strcasecmp(pp,config_get_if()->argv[i] ) == 0 ) { if( prefix == NULL) { config_printhelp(cfgoptions,numoptions,"(root section)"); if ( ! ( CONFIG_ISFLAGSET(CONFIG_NOEXITONHELP))) exit_fun("[CONFIG] Exiting after displaying help\n"); } } else { pp=strtok_r(NULL, " ",&tokctx); if ( prefix != NULL && pp != NULL && strncasecmp(prefix,pp,strlen(pp)) == 0 ) { config_printhelp(cfgoptions,numoptions,prefix); if ( ! (CONFIG_ISFLAGSET(CONFIG_NOEXITONHELP))) { fprintf(stderr,"[CONFIG] %s %i section %s:", __FILE__, __LINE__, prefix); exit_fun(" Exiting after displaying help\n"); } } } } /* now, check for non help options */ if (oneargv[0] == '-') { for(int n=0; n<numoptions; n++) { if ( ( cfgoptions[n].paramflags & PARAMFLAG_DISABLECMDLINE) != 0) { continue; } if (prefix != NULL) { sprintf(cfgpath,"%s.%s",prefix,cfgoptions[n].optname); } else { sprintf(cfgpath,"%s",cfgoptions[n].optname); } if ( ((strlen(oneargv) == 2) && (strcmp(oneargv + 1,cfgpath) == 0)) || /* short option, one "-" */ ((strlen(oneargv) > 2) && (strcmp(oneargv + 2,cfgpath ) == 0 )) ) { char *valptr=NULL; int ret; config_get_if()->argv_info[i] |= CONFIG_CMDLINEOPT_PROCESSED; if (c > 0) { pp = config_get_if()->argv[i+1]; if (pp != NULL ) { ret = strlen(pp); if (ret > 0 ) { if (pp[0] != '-') valptr=pp; else if ( ret > 1 && pp[0] == '-' && isdigit(pp[1]) ) valptr=pp; } } } j += processoption(&(cfgoptions[n]), valptr); if ( valptr != NULL ) { i++; config_get_if()->argv_info[i] |= CONFIG_CMDLINEOPT_PROCESSED; c--; } break; } } /* for n... */ } /* if (oneargv[0] == '-') */ free(oneargv); i++; c--; } /* fin du while */ printf_cmdl("[CONFIG] %s %i options set from command line\n",((prefix == NULL) ? "(root)":prefix),j); return j; } /* parse_cmdline*/