99#include "config.h"
1010#include "utils/logger_helper.h"
1111#include "utils/macros.h"
12+ #include "yaml.h"
1213
1314#define CONFIG_LOGGER "TA"
1415
1516static logger_id_t config_logger_id ;
1617
18+ int get_conf_key (char const * const key ) {
19+ for (int i = 0 ; i < cli_cmd_num ; ++ i ) {
20+ if (!strcmp (ta_cli_arguments_g [i ].name , key )) {
21+ return ta_cli_arguments_g [i ].val ;
22+ }
23+ }
24+
25+ return 0 ;
26+ }
27+
1728struct option * cli_build_options () {
1829 struct option * long_options = (struct option * )malloc (cli_cmd_num * sizeof (struct option ));
1930 for (int i = 0 ; i < cli_cmd_num ; ++ i ) {
@@ -25,12 +36,13 @@ struct option* cli_build_options() {
2536 return long_options ;
2637}
2738
28- status_t cli_config_set (ta_config_t * const info , iota_config_t * const iconf , ta_cache_t * const cache ,
39+ status_t cli_config_set (char * conf_file , ta_config_t * const info , iota_config_t * const iconf , ta_cache_t * const cache ,
2940 iota_client_service_t * const service , int key , char * const value ) {
3041 if (value == NULL || info == NULL || iconf == NULL || cache == NULL || service == NULL ) {
3142 log_error (config_logger_id , "[%s:%d:%s]\n" , __func__ , __LINE__ , "SC_CONF_NULL" );
3243 return SC_CONF_NULL ;
3344 }
45+
3446 switch (key ) {
3547 // TA configuration
3648 case TA_HOST_CLI :
@@ -70,7 +82,21 @@ status_t cli_config_set(ta_config_t* const info, iota_config_t* const iconf, ta_
7082 iconf -> seed = value ;
7183 break ;
7284 case CACHE :
73- cache -> cache_state = !(strncmp (value , "T" , 1 ));
85+ cache -> cache_state = (toupper (value [0 ]) == 'T' );
86+ break ;
87+
88+ // Verbose configuration
89+ case VERBOSE :
90+ verbose_mode = (toupper (value [0 ]) == 'T' );
91+ break ;
92+
93+ // File configuration
94+ case CONF_CLI : {
95+ size_t arg_len = strlen (value );
96+ strncpy (conf_file , value , arg_len );
97+ conf_file [arg_len ] = '\0' ;
98+ break ;
99+ }
74100 }
75101 return SC_OK ;
76102}
@@ -122,6 +148,108 @@ status_t ta_config_default_init(ta_config_t* const info, iota_config_t* const ic
122148 return ret ;
123149}
124150
151+ status_t ta_config_file_init (ta_core_t * const conf , int argc , char * * argv ) {
152+ int key = 0 ;
153+ status_t ret = SC_OK ;
154+ struct option * long_options = cli_build_options ();
155+ yaml_parser_t parser ;
156+ yaml_token_t token ;
157+ FILE * file = NULL ;
158+ char * arg = NULL ;
159+ int state = 0 ;
160+
161+ // Initialize default configuration file path with '\0'
162+ conf -> conf_file [0 ] = '\0' ;
163+
164+ if (!yaml_parser_initialize (& parser )) {
165+ ret = SC_CONF_PARSER_ERROR ;
166+ log_error (config_logger_id , "[%s:%d:%s]\n" , __func__ , __LINE__ , "SC_CONF_PARSER_ERROR" );
167+ goto done ;
168+ }
169+
170+ // Loop through the CLI arguments for first time to find the configuration file path
171+ while ((key = getopt_long (argc , argv , "hv" , long_options , NULL )) != -1 ) {
172+ switch (key ) {
173+ case ':' :
174+ ret = SC_CONF_MISSING_ARGUMENT ;
175+ log_error (config_logger_id , "[%s:%d:%s]\n" , __func__ , __LINE__ , "SC_CONF_MISSING_ARGUMENT" );
176+ break ;
177+ case '?' :
178+ ret = SC_CONF_UNKNOWN_OPTION ;
179+ log_error (config_logger_id , "[%s:%d:%s]\n" , __func__ , __LINE__ , "SC_CONF_UNKNOWN_OPTION" );
180+ break ;
181+ case CONF_CLI :
182+ ret = cli_config_set (conf -> conf_file , & conf -> info , & conf -> iconf , & conf -> cache , & conf -> service , key , optarg );
183+ break ;
184+ default :
185+ break ;
186+ }
187+ if (ret != SC_OK ) {
188+ break ;
189+ }
190+ }
191+
192+ // Reset the CLI option index for the second loop where they are actually analyzed
193+ optind = 1 ;
194+
195+ if (strlen (conf -> conf_file ) == 0 ) {
196+ /* No configuration file specified */
197+ ret = SC_OK ;
198+ goto done ;
199+ }
200+
201+ if ((file = fopen (conf -> conf_file , "r" )) == NULL ) {
202+ /* The specified configuration file does not exist */
203+ ret = SC_CONF_FOPEN_ERROR ;
204+ log_error (config_logger_id , "[%s:%d:%s]\n" , __func__ , __LINE__ , "SC_CONF_FOPEN_ERROR" );
205+ goto done ;
206+ }
207+
208+ yaml_parser_set_input_file (& parser , file );
209+
210+ do { /* start reading tokens */
211+ if (!yaml_parser_scan (& parser , & token )) {
212+ ret = SC_CONF_PARSER_ERROR ;
213+ log_error (config_logger_id , "[%s:%d:%s]\n" , __func__ , __LINE__ , "SC_CONF_PARSER_ERROR" );
214+ goto done ;
215+ }
216+ switch (token .type ) {
217+ case YAML_KEY_TOKEN :
218+ state = 0 ;
219+ break ;
220+ case YAML_VALUE_TOKEN :
221+ state = 1 ;
222+ break ;
223+ case YAML_SCALAR_TOKEN :
224+ arg = (char * )token .data .scalar .value ;
225+ if (state == 0 ) { // Key
226+ key = get_conf_key (arg );
227+ } else { // Value
228+ if ((ret = cli_config_set (conf -> conf_file , & conf -> info , & conf -> iconf , & conf -> cache , & conf -> service , key ,
229+ strdup (arg ))) != SC_OK ) {
230+ goto done ;
231+ }
232+ }
233+ break ;
234+ default :
235+ break ;
236+ }
237+ if (token .type != YAML_STREAM_END_TOKEN ) {
238+ yaml_token_delete (& token );
239+ }
240+ } while (token .type != YAML_STREAM_END_TOKEN );
241+
242+ done :
243+ yaml_token_delete (& token );
244+ yaml_parser_delete (& parser );
245+ if (file ) {
246+ fclose (file );
247+ }
248+ free (long_options );
249+
250+ return ret ;
251+ }
252+
125253status_t ta_config_cli_init (ta_core_t * const conf , int argc , char * * argv ) {
126254 int key = 0 ;
127255 status_t ret = SC_OK ;
@@ -131,9 +259,11 @@ status_t ta_config_cli_init(ta_core_t* const conf, int argc, char** argv) {
131259 switch (key ) {
132260 case ':' :
133261 ret = SC_CONF_MISSING_ARGUMENT ;
262+ log_error (config_logger_id , "[%s:%d:%s]\n" , __func__ , __LINE__ , "SC_CONF_MISSING_ARGUMENT" );
134263 break ;
135264 case '?' :
136265 ret = SC_CONF_UNKNOWN_OPTION ;
266+ log_error (config_logger_id , "[%s:%d:%s]\n" , __func__ , __LINE__ , "SC_CONF_UNKNOWN_OPTION" );
137267 break ;
138268 case 'h' :
139269 ta_usage ();
@@ -148,8 +278,11 @@ status_t ta_config_cli_init(ta_core_t* const conf, int argc, char** argv) {
148278 // Enable backend_redis logger
149279 br_logger_init ();
150280 break ;
281+ case CONF_CLI :
282+ /* Already processed in ta_config_file_init() */
283+ break ;
151284 default :
152- ret = cli_config_set (& conf -> info , & conf -> iconf , & conf -> cache , & conf -> service , key , optarg );
285+ ret = cli_config_set (conf -> conf_file , & conf -> info , & conf -> iconf , & conf -> cache , & conf -> service , key , optarg );
153286 break ;
154287 }
155288 if (ret != SC_OK ) {
0 commit comments