xref: /aosp_15_r20/external/libconfig/contrib/ls-config/src/ls-config.c (revision 2e9d491483b805f09ea864149eadd5680efcc72a)
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <limits.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <getopt.h>
7 #include <locale.h>
8 #include <libintl.h>
9 #include <errno.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <math.h>
14 #include <libconfig.h>
15 
16 #define PACKAGE    "LS bash config"
17 #define VERSION    "1.0.3"
18 
19 // global flags
20 struct flags {
21 	int quiet; //quiet output
22 	int names; //set for printout config variables names
23 	int types; //set for printout config variables types
24 	int values; //set for printout config variables values
25 	int indexes; //set for printout config variables indexes
26 	int counter; //set for printout config varibales counting (for grout, list, array. in other cases it return 1)
27 	int unset; //unset valriable
28 	int boolstring; //set for output bool variable (0|1) as test (false|true)
29 	int mode; //1 - for setting variable, 0 - for get hist data
30 	int error; //error status handling
31 };
32 
33 //take valur from input and comvert it to int
34 //TODO: Read long too
getNumber()35 int getNumber() {
36   char buf[1000];
37   int test,val;
38   unsigned int inp;
39   fgets(buf, sizeof buf, stdin);
40   test = sscanf(buf, "%u", &inp);
41   val = (int) inp;
42   if(val < 0) val *= -1;
43   if(test > 0) return val;
44   return (int) 0;
45 }
46 
47 //printout help messsage
printHelp()48 void printHelp() {
49 	printf(gettext("Configuration file handling\n"));
50 	printf("\n");
51 	printf(gettext("Usage: ls-config [OPTION]\n"));
52 	printf(gettext("Reading and writening data from configuration files\n"));
53 	printf(gettext("in libconfig9 format.\n"));
54 	printf("\n");
55 	printf(gettext("CAUTION: using without given config file are cause error!\n"));
56 	printf("\n");
57 	printf(gettext("Available options:\n"));
58 	printf(gettext("   -f, --file=FILE       Configuration file to handle.\n"));
59 	printf("\n");
60 	printf(gettext("   -s, --set=PATH        Set configuration variable of given path.\n"));
61 	printf(gettext("   -d, --data=DATA       Configuration variable value (only with -s)\n"));
62 	printf(gettext("   -p, --type=TYPE       Configuration value type\n"));
63 	printf("\n");
64 	printf(gettext("   -g, --get=PATH        Get configuration variable of given path.\n"));
65 	printf(gettext("   -n, --names           Printout variables names.\n"));
66 	printf(gettext("   -t, --types           Printout variables types.\n"));
67 	printf(gettext("   -v, --values          Printout variables values.\n"));
68 	printf(gettext("   -i, --indexes         Printout variables indexes.\n"));
69 	printf(gettext("   -c, --count           Printout elements count (only: array, list, group).\n"));
70 	printf(gettext("   -b, --bool-string     Printout boolean variables as text.\n"));
71 	printf("\n");
72 	printf(gettext("   -q, --quiet           Quiet output to use in scripts.\n"));
73 	printf(gettext("   -h, --help            Print this help message.\n"));
74 	printf("\n");
75 	printf(gettext("TYPE:    Variable types:\n"));
76 	printf(gettext("         group  - variables group,\n"));
77 	printf(gettext("         array  - array of variables,\n"));
78 	printf(gettext("         list   - list of variables,\n"));
79 	printf(gettext("         int    - integer number,\n"));
80 	printf(gettext("         int64  - 64bit integer number,\n"));
81 	printf(gettext("         float  - float point number,\n"));
82 	printf(gettext("         bool   - boolean value,\n"));
83 	printf(gettext("         string - character string.\n"));
84 	printf("\n");
85 	printf("(c) 2013 by LucaS web sutio - http://www.lucas.net.pl\n");
86 	printf("Author: Łukasz A. Grabowski\n");
87    printf(gettext("Licence: "));
88 	printf("GPL v2.\n");
89    exit(0);
90 };
91 
92 //set configuration int value
set_config_int(config_setting_t * setting,char * dataString,struct flags optflags)93 int set_config_int(config_setting_t *setting, char *dataString, struct flags optflags) {
94 	long bufl; //int (long) to get from input data string
95 	int buf, scs; //config int, success status
96 	char *erp; //error output
97 
98 	//convert input data to int
99 	errno = 0;
100 	bufl = strtol(dataString, &erp, 0);
101 	if(((errno == ERANGE && (bufl == LONG_MAX || bufl == LONG_MIN)) || (errno != 0 && bufl == 0)) || (erp == dataString) || bufl > INT_MAX || bufl < INT_MIN) {
102 		if(optflags.quiet == 0) printf(gettext("ERROR! Incorrect data format.\n"));
103   			return 12;
104 		};
105 	buf = (int)bufl;
106 
107 	//set configuration variable
108 	scs = config_setting_set_int(setting, buf);
109 	if(scs == CONFIG_FALSE) {
110 		if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
111 		return 11;
112 	};
113 	return 0;
114 };
115 
116 //set configuration int64 value
set_config_int64(config_setting_t * setting,char * dataString,struct flags optflags)117 int set_config_int64(config_setting_t *setting, char *dataString, struct flags optflags) {
118 	long bufl; //long to get from input data string
119 	int scs; //success status
120 	char *erp; //error output
121 
122 	//convert input data to long
123 	errno = 0;
124 	bufl = strtol(dataString, &erp, 0);
125 	if(((errno == ERANGE && (bufl == LONG_MAX || bufl == LONG_MIN)) || (errno != 0 && bufl == 0)) || (erp == dataString)) {
126 		if(optflags.quiet == 0) printf(gettext("ERROR! Incorrect data format.\n"));
127 			return 12;
128 		};
129 
130 	//set configuration variable
131 	scs = config_setting_set_int64(setting, bufl);
132 	if(scs == CONFIG_FALSE) {
133 		if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
134 		return 11;
135 	};
136 	return 0;
137 };
138 
139 //set configuration float value
set_config_float(config_setting_t * setting,char * dataString,struct flags optflags)140 int set_config_float(config_setting_t *setting, char *dataString, struct flags optflags) {
141 	double buff; //double (float) to get from input data string
142 	int scs; //success status
143 	char *erp; //error output
144 
145 	//convert input data to double
146 	errno = 0;
147 	buff = strtod(dataString, &erp);
148    if(((errno == ERANGE && (buff == HUGE_VALF || buff == HUGE_VALL)) || (errno != 0 && buff == 0)) || (erp == dataString)) {
149 		if(optflags.quiet == 0) printf(gettext("ERROR! Incorrect data format.\n"));
150 		return 12;
151 	}
152 
153 	//set configuration variable
154 	scs = config_setting_set_float(setting, buff);
155 	if(scs == CONFIG_FALSE) {
156 		if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
157 		return 11;
158 	};
159 	return 0;
160 };
161 
162 //set configuration boolean value
set_config_bool(config_setting_t * setting,char * dataString,struct flags optflags)163 int set_config_bool(config_setting_t *setting, char *dataString, struct flags optflags) {
164 	int scs, buf; //success status, input convert burrer
165 
166 	//convert input data
167 	//chceck both 1/0 and true/false string
168 	buf = -1;
169 	if(!strcmp(dataString, "1") || !strcmp(dataString, "true") || !strcmp(dataString, "TRUE")) buf = 1;
170 	if(!strcmp(dataString, "0") || !strcmp(dataString, "false") || !strcmp(dataString, "FALSE")) buf = 0;
171 	if(buf < 0) {
172 		if(optflags.quiet == 0) printf(gettext("ERROR! Incorrect data format.\n"));
173 		return 12;
174 	}
175 
176 	//set configuration variable
177 	scs = config_setting_set_bool(setting, buf);
178 	if(scs == CONFIG_FALSE) {
179 		if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
180 		return 11;
181 	};
182 	return 0;
183 };
184 
185 //configuratnion variable path look like: foo.bar.car
186 //this fuction return string giving path to parent element (foo.bar)
path_parent(char * dataPath)187 char* path_parent(char *dataPath) {
188 	char *str_ptr, *last_ptr, *newpath, *dot="."; //tokenized buffer, last buffer, new parent path, separator
189 	newpath = malloc(1);
190 	memset(newpath, 0, 1);
191 	last_ptr = malloc(1);
192 	memset(last_ptr, 0, 1);
193 
194 	//tokenize string and save last token
195 	str_ptr = strtok(dataPath, ".");
196 	last_ptr = (char*)realloc(last_ptr, (strlen(str_ptr)+1)*sizeof(char));
197 	strcpy(last_ptr, str_ptr);
198 
199 	//loop overt path to build new path without last element
200 	while(str_ptr != NULL) {
201 		str_ptr = strtok(NULL, ".");
202 		if(str_ptr != NULL) {
203 			if(strlen(last_ptr) > 0 ) {
204 				newpath = (char*)realloc(newpath, (strlen(newpath)+strlen(last_ptr)+2)*sizeof(char));
205 				strcat(newpath, dot);
206 				strcat(newpath, last_ptr);
207 			};
208 			last_ptr = (char*)realloc(last_ptr, (strlen(str_ptr)+1)*sizeof(char));
209 			strcpy(last_ptr, str_ptr);
210 		} else {
211 			last_ptr = (char*)realloc(last_ptr, (1)*sizeof(char));
212 			memset(last_ptr, 0, 1);
213 		};
214   	};
215 	free(dataPath);
216 
217 	//if new path empty thren return null
218 	if(strlen(newpath) == 0) {
219 		free(newpath);
220 		newpath = NULL;
221 	};
222 	return newpath;
223 };
224 
225 //get element name from configuration variable path
226 //e.g.: from foo.bar return bar
path_name(char * dataPath)227 char* path_name(char *dataPath) {
228 	char *str_ptr, *name, *tk; //tokenized buffer, element name, copy of dataPath
229 	name = malloc(1);
230 
231 	//make copy of dataPath
232 	tk = malloc((strlen(dataPath)+1)*sizeof(char));
233 	memset(name, 0, 1);
234 	strcpy(tk, dataPath);
235 
236 	//tokenize dataPath
237 	str_ptr = strtok(tk, ".");
238 
239 	//loop over tokenize pathh to get last element
240 	while(str_ptr != NULL) {
241 		name = (char*)realloc(name, (strlen(str_ptr)+1)*sizeof(char));
242 		strcpy(name, str_ptr);
243 		str_ptr = strtok(NULL, ".");
244   	};
245 	free(tk);
246 
247 	//if no element name then return null
248 	if(strlen(name) == 0) {
249 		free(name);
250 		name = NULL;
251 	};
252 	return name;
253 };
254 
255 //set configuration path
256 //@return int success
257 //@param configFile - name (with path) of configuration fille
258 //@param dataPath - path of configuration variable (in config file)
259 //@param optflags - global options flags
260 //@param dataString - data to store in configuration variable in string format
261 //@param dataType - type of variable to save
set_config(char * configFile,char * dataPath,struct flags optflags,char * dataString,char * dataType)262 int set_config(char *configFile, char *dataPath, struct flags optflags, char *dataString, char *dataType) {
263 	config_t cfg; //libcongig configuration handler
264 	config_setting_t *setting, *ss; //libconfig element handrer: mant, and subset (uset for multielement types)
265 	config_init(&cfg);
266 	int scs, dt, dattyp; //sucess statu, data type
267 	char *npath; // new variable configuration path path
268 
269 	//open and read configuration file
270 	if(!config_read_file(&cfg, configFile)) {
271   		config_destroy(&cfg);
272 		if(optflags.quiet == 0) printf(gettext("ERROR! Can't read configuration file.\n"));
273   		return 1;
274  	};
275 
276 	//if no data path or data string then cause error
277 	if(dataPath == NULL) {
278   		config_destroy(&cfg);
279 		if(optflags.quiet == 0) printf(gettext("ERROR! Conviguration variable path not given.\n"));
280   		return 4;
281 	};
282 	if(dataString == NULL) {
283   		config_destroy(&cfg);
284 		if(optflags.quiet == 0) printf(gettext("ERROR! Configuration variable value not given.\n"));
285   		return 9;
286 	};
287 
288  	//find configuration variable of given path
289 	setting = config_lookup(&cfg, dataPath);
290 	if(setting == NULL) {
291 		//if variable of given path not found get element name and partent path,
292 		//then try to create it
293 		npath = path_name(dataPath);
294 		dataPath = path_parent(dataPath);
295 		if(dataPath == NULL) {
296 			setting = config_root_setting(&cfg);
297 		} else {
298 			setting = config_lookup(&cfg, dataPath);
299 		};
300 		if(setting == NULL) {
301 			//if parent not exists exit with error
302 			config_destroy(&cfg);
303 			if(optflags.quiet == 0) printf(gettext("ERROR! Inavlid configuration variable path.\n"));
304   			return 16;
305 		};
306 		//chceck type of parent element (named alement can be added only to group element)
307 		dt = config_setting_type(setting);
308 		if(dt != CONFIG_TYPE_GROUP) {
309 			config_destroy(&cfg);
310 			if(optflags.quiet == 0) printf(gettext("ERROR! New named configuration variable can be added only to group element.\n"));
311   			return 17;
312 		};
313 		//check if new element type are given
314 		if(dataType == NULL) {
315 			config_destroy(&cfg);
316 			if(optflags.quiet == 0) printf(gettext("ERROR! Configuration variable type not given.\n"));
317   			return 13;
318 		};
319 		//now get type based on his name
320 		if(!strcmp(dataType, "int")) {
321 			dattyp = CONFIG_TYPE_INT;
322 		} else if(!strcmp(dataType, "int64")) {
323 			dattyp = CONFIG_TYPE_INT64;
324 		} else if(!strcmp(dataType, "float")) {
325 			dattyp = CONFIG_TYPE_FLOAT;
326 		} else if(!strcmp(dataType, "string")) {
327 			dattyp = CONFIG_TYPE_STRING;
328 		} else if(!strcmp(dataType, "bool")) {
329 			dattyp = CONFIG_TYPE_BOOL;
330 		} else if(!strcmp(dataType, "array")) {
331 			dattyp = CONFIG_TYPE_ARRAY;
332 		} else if(!strcmp(dataType, "list")) {
333 			dattyp = CONFIG_TYPE_LIST;
334 		} else if(!strcmp(dataType, "group")) {
335 			dattyp = CONFIG_TYPE_GROUP;
336 		} else {
337 			//if given type no mutch eny then cause error and exit
338 			config_destroy(&cfg);
339 			if(optflags.quiet == 0) printf(gettext("ERROR! Inlegal data type.\n"));
340   			return 14;
341 		};
342 		//add new element to configuration file
343 		ss = config_setting_add(setting, npath, dattyp);
344 		if(ss == NULL) {
345 			config_destroy(&cfg);
346 			if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
347   			return 11;
348 		};
349 		scs = 0;
350 		//and based on new type set his value
351 		switch(dattyp) {
352 			case CONFIG_TYPE_INT:
353 				scs = set_config_int(ss, dataString, optflags);
354 				break;
355 			case CONFIG_TYPE_INT64:
356 				scs = set_config_int64(ss, dataString, optflags);
357 				break;
358 			case CONFIG_TYPE_FLOAT:
359 				scs = set_config_float(ss, dataString, optflags);
360 				break;
361 			case CONFIG_TYPE_STRING:
362 				scs = config_setting_set_string(ss, dataString);
363 				if(scs == CONFIG_FALSE) {
364 					if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
365   					scs = 11;
366 				} else scs = 0;
367 				break;
368 			case CONFIG_TYPE_BOOL:
369 				scs = set_config_bool(ss, dataString, optflags);
370 				break;
371 		};
372 		if(scs > 0) {
373 			//if occurs some error wihe setting variable value exit with error
374 			config_destroy(&cfg);
375 			return scs;
376       };
377 	} else {
378 		//but if we found element of given path, try to set his value
379 		//first of all determinate type of value
380 		dt = config_setting_type(setting);
381 		switch(dt) {
382 			case CONFIG_TYPE_INT:
383 				if(dataType != NULL && strcmp(dataType, "int")) {
384 					config_destroy(&cfg);
385 					if(optflags.quiet == 0) printf(gettext("ERROR! inconsistent value type.\n"));
386   					return 10;
387 				};
388 				//then set value
389 				scs = set_config_int(setting, dataString, optflags);
390 				if(scs > 0) {
391 					config_destroy(&cfg);
392   					return scs;
393 				};
394 				break;
395 			case CONFIG_TYPE_INT64:
396 				if(dataType != NULL && strcmp(dataType, "int64")) {
397 					config_destroy(&cfg);
398 					if(optflags.quiet == 0) printf(gettext("ERROR! inconsistent value type.\n"));
399   					return 10;
400 				};
401 				//then set value
402 				scs = set_config_int64(setting, dataString, optflags);
403 				if(scs > 0) {
404 					config_destroy(&cfg);
405   					return scs;
406 				};
407 				break;
408 			case CONFIG_TYPE_FLOAT:
409 				if(dataType != NULL && strcmp(dataType, "float")) {
410 					config_destroy(&cfg);
411 					if(optflags.quiet == 0) printf(gettext("ERROR! inconsistent value type.\n"));
412   					return 10;
413 				};
414 				//then set value
415 				scs = set_config_float(setting, dataString, optflags);
416 				if(scs > 0) {
417 					config_destroy(&cfg);
418   					return scs;
419 				};
420 				break;
421 			case CONFIG_TYPE_STRING:
422 				if(dataType != NULL && strcmp(dataType, "string")) {
423 					config_destroy(&cfg);
424 					if(optflags.quiet == 0) printf(gettext("ERROR! inconsistent value type.\n"));
425   					return 10;
426 				};
427 				//then set value
428 				scs = config_setting_set_string(setting, dataString);
429 				if(scs == CONFIG_FALSE) {
430 					config_destroy(&cfg);
431 					if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
432   					return 11;
433 				};
434 				break;
435 			case CONFIG_TYPE_BOOL:
436 				if(dataType != NULL && strcmp(dataType, "bool")) {
437 					config_destroy(&cfg);
438 					if(optflags.quiet == 0) printf(gettext("ERROR! inconsistent value type.\n"));
439   					return 10;
440 				};
441 				//then set value
442 				scs = set_config_bool(setting, dataString, optflags);
443 				if(scs > 0) {
444 					config_destroy(&cfg);
445   					return scs;
446 				};
447 				break;
448 			case CONFIG_TYPE_ARRAY:
449 				//if array are empty we can set alement of any scalar type
450 				if(config_setting_length(setting) == 0) {
451 					//but we must have his type
452 					if(dataType == NULL) {
453 						config_destroy(&cfg);
454 						if(optflags.quiet == 0) printf(gettext("ERROR! Configuration variable type not given.\n"));
455   						return 13;
456 					};
457 					if(!strcmp(dataType, "int")) {
458 						dattyp = CONFIG_TYPE_INT;
459 					} else if(!strcmp(dataType, "int64")) {
460 						dattyp = CONFIG_TYPE_INT64;
461 					} else if(!strcmp(dataType, "float")) {
462 						dattyp = CONFIG_TYPE_FLOAT;
463 					} else if(!strcmp(dataType, "string")) {
464 						dattyp = CONFIG_TYPE_STRING;
465 					} else if(!strcmp(dataType, "bool")) {
466 						dattyp = CONFIG_TYPE_BOOL;
467 					} else {
468 						//only scalar type availabe
469 						config_destroy(&cfg);
470 						if(optflags.quiet == 0) printf(gettext("ERROR! Prohibited data type.\n"));
471   						return 18;
472 					};
473 					//first of all we must add new element to array
474 					ss = config_setting_add(setting, NULL, dattyp);
475 					if(ss == NULL) {
476 						config_destroy(&cfg);
477 						if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
478   						return 11;
479 					};
480 					//then based on his type set value
481 					switch(dattyp) {
482 						case CONFIG_TYPE_INT:
483 							scs = set_config_int(ss, dataString, optflags);
484 							if(scs > 0) {
485 								config_destroy(&cfg);
486   								return scs;
487 							};
488 							break;
489 						case CONFIG_TYPE_INT64:
490 							scs = set_config_int64(ss, dataString, optflags);
491 							if(scs > 0) {
492 								config_destroy(&cfg);
493   								return scs;
494 							};
495 							break;
496 						case CONFIG_TYPE_FLOAT:
497 							scs = set_config_float(ss, dataString, optflags);
498 							if(scs > 0) {
499 								config_destroy(&cfg);
500   								return scs;
501 							};
502 							break;
503 						case CONFIG_TYPE_STRING:
504 							scs = config_setting_set_string(ss, dataString);
505 							if(scs == CONFIG_FALSE) {
506 								config_destroy(&cfg);
507 								if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
508   								return 11;
509 							};
510 							break;
511 						case CONFIG_TYPE_BOOL:
512 							scs = set_config_bool(ss, dataString, optflags);
513 							if(scs > 0) {
514 								config_destroy(&cfg);
515   								return scs;
516 							};
517 							break;
518 					};
519 				} else {
520 					//but if we have some element in array, we can add only element of same type
521 					//so, because all element in arry must be same type, we get type of first element
522 					//and based on it set new element
523 					dattyp = config_setting_type(config_setting_get_elem(setting, 0));
524 					switch(dattyp) {
525 						case CONFIG_TYPE_INT:
526 							if(dataType != NULL && strcmp(dataType, "int")) {
527 								config_destroy(&cfg);
528 								if(optflags.quiet == 0) printf(gettext("ERROR! inconsistent value type.\n"));
529   								return 10;
530 							};
531 							//add new element
532 							ss = config_setting_add(setting, NULL, dattyp);
533 							if(ss == NULL) {
534 								config_destroy(&cfg);
535 								if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
536   								return 11;
537 							};
538 							//then set his value
539 							scs = set_config_int(ss, dataString, optflags);
540 							if(scs > 0) {
541 								config_destroy(&cfg);
542 								return scs;
543 							};
544 							break;
545 						case CONFIG_TYPE_INT64:
546 							if(dataType != NULL && strcmp(dataType, "int64")) {
547 								config_destroy(&cfg);
548 								if(optflags.quiet == 0) printf(gettext("ERROR! inconsistent value type.\n"));
549   								return 10;
550 							};
551 							//add new element
552 							ss = config_setting_add(setting, NULL, dattyp);
553 							if(ss == NULL) {
554 								config_destroy(&cfg);
555 								if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
556   								return 11;
557 							};
558 							//then set his value
559 							scs = set_config_int64(ss, dataString, optflags);
560 							if(scs > 0) {
561 								config_destroy(&cfg);
562 								return scs;
563 							};
564 							break;
565 						case CONFIG_TYPE_FLOAT:
566 							if(dataType != NULL && strcmp(dataType, "float")) {
567 								config_destroy(&cfg);
568 								if(optflags.quiet == 0) printf(gettext("ERROR! inconsistent value type.\n"));
569   								return 10;
570 							};
571 							//add new element
572 							ss = config_setting_add(setting, NULL, dattyp);
573 							if(ss == NULL) {
574 								config_destroy(&cfg);
575 								if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
576   								return 11;
577 							};
578 							//then set his value
579 							scs = set_config_float(ss, dataString, optflags);
580 							if(scs > 0) {
581 								config_destroy(&cfg);
582 								return scs;
583 							};
584 							break;
585 						case CONFIG_TYPE_STRING:
586 							if(dataType != NULL && strcmp(dataType, "string")) {
587 								config_destroy(&cfg);
588 								if(optflags.quiet == 0) printf(gettext("ERROR! inconsistent value type.\n"));
589   								return 10;
590 							};
591 							//add new element
592 							ss = config_setting_add(setting, NULL, dattyp);
593 							if(ss == NULL) {
594 								config_destroy(&cfg);
595 								if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
596   								return 11;
597 							};
598 							//then set his value
599 							scs = config_setting_set_string(ss, dataString);
600 							if(scs == CONFIG_FALSE) {
601 								config_destroy(&cfg);
602 								if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
603   								return 11;
604 							};
605 							break;
606 						case CONFIG_TYPE_BOOL:
607 							if(dataType != NULL && strcmp(dataType, "bool")) {
608 								config_destroy(&cfg);
609 								if(optflags.quiet == 0) printf(gettext("ERROR! inconsistent value type.\n"));
610   								return 10;
611 							};
612 							//add new element
613 							ss = config_setting_add(setting, NULL, dattyp);
614 							if(ss == NULL) {
615 								config_destroy(&cfg);
616 								if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
617   								return 11;
618 							};
619 							//then set his value
620 							scs = set_config_bool(ss, dataString, optflags);
621 							if(scs > 0) {
622 								config_destroy(&cfg);
623 								return scs;
624 							};
625 							break;
626 					};
627 				};
628 				break;
629 			case CONFIG_TYPE_LIST:
630 				//in case adding element to list, we can add any type of element
631 				if(dataType == NULL) {
632 					//but we must konwn his type
633 					config_destroy(&cfg);
634 					if(optflags.quiet == 0) printf(gettext("ERROR! Configuration variable type not given.\n"));
635   					return 13;
636 				};
637 				if(!strcmp(dataType, "int")) {
638 					dattyp = CONFIG_TYPE_INT;
639 				} else if(!strcmp(dataType, "int64")) {
640 					dattyp = CONFIG_TYPE_INT64;
641 				} else if(!strcmp(dataType, "float")) {
642 					dattyp = CONFIG_TYPE_FLOAT;
643 				} else if(!strcmp(dataType, "string")) {
644 					dattyp = CONFIG_TYPE_STRING;
645 				} else if(!strcmp(dataType, "bool")) {
646 					dattyp = CONFIG_TYPE_BOOL;
647 				} else if(!strcmp(dataType, "array")) {
648 					dattyp = CONFIG_TYPE_ARRAY;
649 				} else if(!strcmp(dataType, "list")) {
650 					dattyp = CONFIG_TYPE_LIST;
651 				} else if(!strcmp(dataType, "group")) {
652 					dattyp = CONFIG_TYPE_GROUP;
653 				} else {
654 					config_destroy(&cfg);
655 					if(optflags.quiet == 0) printf(gettext("ERROR! Inlegal data type.\n"));
656   					return 14;
657 				};
658 				//add new element of given type
659 				ss = config_setting_add(setting, NULL, dattyp);
660 				if(ss == NULL) {
661 					config_destroy(&cfg);
662 					if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
663   					return 11;
664 				};
665 				//now, based on type, set element value
666 				scs = 0;
667 				switch(dattyp) {
668 					case CONFIG_TYPE_INT:
669 						scs = set_config_int(ss, dataString, optflags);
670 						break;
671 					case CONFIG_TYPE_INT64:
672 						scs = set_config_int64(ss, dataString, optflags);
673 						break;
674 					case CONFIG_TYPE_FLOAT:
675 						scs = set_config_int64(ss, dataString, optflags);
676 						break;
677 					case CONFIG_TYPE_STRING:
678 						scs = config_setting_set_string(ss, dataString);
679 						if(scs == CONFIG_FALSE) {
680 							config_destroy(&cfg);
681 							if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
682   							return 11;
683 						};
684 						scs = 0;
685 						break;
686 					case CONFIG_TYPE_BOOL:
687 						scs = set_config_int64(ss, dataString, optflags);
688 						break;
689 				};
690 				if(scs > 0) {
691 					config_destroy(&cfg);
692   					return scs;
693 				};
694 				//finaly outpt index of new added element
695 				if(optflags.quiet == 0) {
696 					printf(gettext("Added element index: %d\n"), config_setting_index(ss));
697 				} else {
698 					printf("%d", config_setting_index(ss));
699 				};
700 				break;
701 			case CONFIG_TYPE_GROUP:
702 				//to group we can add any type of element, but we must have his name
703 				if(dataType == NULL) {
704 					config_destroy(&cfg);
705 					if(optflags.quiet == 0) printf(gettext("ERROR! Configuration variable type not given.\n"));
706   					return 13;
707 				};
708 				if(strlen(dataString) < 1) {
709 					config_destroy(&cfg);
710 					if(optflags.quiet == 0) printf(gettext("ERROR! Bad name of configuration variable.\n"));
711   					return 15;
712 				};
713 				//determinate type of new variable
714 				if(!strcmp(dataType, "int")) {
715 					dattyp = CONFIG_TYPE_INT;
716 				} else if(!strcmp(dataType, "int64")) {
717 					dattyp = CONFIG_TYPE_INT64;
718 				} else if(!strcmp(dataType, "float")) {
719 					dattyp = CONFIG_TYPE_FLOAT;
720 				} else if(!strcmp(dataType, "string")) {
721 					dattyp = CONFIG_TYPE_STRING;
722 				} else if(!strcmp(dataType, "bool")) {
723 					dattyp = CONFIG_TYPE_BOOL;
724 				} else if(!strcmp(dataType, "array")) {
725 					dattyp = CONFIG_TYPE_ARRAY;
726 				} else if(!strcmp(dataType, "list")) {
727 					dattyp = CONFIG_TYPE_LIST;
728 				} else if(!strcmp(dataType, "group")) {
729 					dattyp = CONFIG_TYPE_GROUP;
730 				} else {
731 					config_destroy(&cfg);
732 					if(optflags.quiet == 0) printf(gettext("ERROR! Inlegal data type.\n"));
733   					return 14;
734 				};
735 				//then add new alement
736 				ss = config_setting_add(setting, dataString, dattyp);
737 				if(ss == NULL) {
738 					config_destroy(&cfg);
739 					if(optflags.quiet == 0) printf(gettext("ERROR! Variable set failed.\n"));
740   					return 11;
741 				};
742 				//in case of adding new element to group we not set his value
743 				//(value field of input are used to get variable name)
744 				//We only output index of new added element
745 				if(optflags.quiet == 0) {
746 					printf(gettext("Added element index: %d\n"), config_setting_index(ss));
747 				} else {
748 					printf("%d", config_setting_index(ss));
749 				};
750 				break;
751 		};
752 	}
753 
754 	//Finaly write configuration file
755 	scs = config_write_file(&cfg, configFile);
756 	if(scs == CONFIG_FALSE) {
757   		config_destroy(&cfg);
758 		if(optflags.quiet == 0) printf(gettext("ERROR! Configuration file write failed.\n"));
759   		return 8;
760  	};
761  	config_destroy(&cfg);
762 	return 0;
763 };
764 
765 //unset configuration path
766 //(remove variable from configuration file)
767 //@return int success
768 //@param char* configFile - the name (with path) of configuration file
769 //@param char* configPath - path to configuration valriable to remove (unset)
770 //@param struct flags optflags - global flags
unset_config(char * configFile,char * dataPath,struct flags optflags)771 int unset_config(char *configFile, char *dataPath, struct flags optflags) {
772 	config_t cfg; //configuration file handler
773 	config_setting_t *setting, *par; //configuration valriale handler, and paren variable handler
774 	int idx, scs; //index of variable, sucess status
775 	//open configuration file
776 	config_init(&cfg);
777 	if(!config_read_file(&cfg, configFile)) {
778   		config_destroy(&cfg);
779 		if(optflags.quiet == 0) printf(gettext("ERROR! Can't read configuration file.\n"));
780   		return 1;
781  	};
782 	//chceck if data path given
783 	if(dataPath == NULL) {
784   		config_destroy(&cfg);
785 		if(optflags.quiet == 0) printf(gettext("ERROR! Conviguration variable path not given.\n"));
786   		return 4;
787 	};
788 	//now find variable of given path
789 	setting = config_lookup(&cfg, dataPath);
790 	if(setting == NULL) {
791   		config_destroy(&cfg);
792 		if(optflags.quiet == 0) printf(gettext("ERROR! Given variable path not found.\n"));
793   		return 3;
794  	};
795 	//get element index
796 	idx = config_setting_index(setting);
797 	if(idx < 0) {
798   		config_destroy(&cfg);
799 		if(optflags.quiet == 0) printf(gettext("ERROR! Can't remove root element.\n"));
800   		return 5;
801  	};
802 	//now find parent element
803 	par = config_setting_parent(setting);
804 	if(par == NULL) {
805   		config_destroy(&cfg);
806 		if(optflags.quiet == 0) printf(gettext("ERROR! Can't find parent element.\n"));
807   		return 6;
808  	};
809 	//then remove element
810 	scs = config_setting_remove_elem(par, idx);
811 	if(scs == CONFIG_FALSE) {
812   		config_destroy(&cfg);
813 		if(optflags.quiet == 0) printf(gettext("ERROR! Variable unset failed.\n"));
814   		return 7;
815  	};
816 	//Finaly write configuration file
817 	scs = config_write_file(&cfg, configFile);
818 	if(scs == CONFIG_FALSE) {
819   		config_destroy(&cfg);
820 		if(optflags.quiet == 0) printf(gettext("ERROR! Configuration file write failed.\n"));
821   		return 8;
822  	};
823  	config_destroy(&cfg);
824 	return 0;
825 };
826 
827 //get configuratioin variable
828 //(read it from configuration file)
829 //@return char* variable value
830 //@param char* configFile - configuration file name (with path)
831 //@param cher* dataPath - configuration variable path (in file)
832 //@param struct flags optflags - global flags
read_config(char * configFile,char * dataPath,struct flags optflags)833 int read_config(char *configFile, char *dataPath, struct flags optflags) {
834 	config_t cfg; //configuration file handler
835 	config_setting_t *setting, *ss; //configuration element handler, and helper handler (config element too)
836 	int comaset, varindex, varcounter; //helper flat for buid output strings, varibale index, counter
837 	unsigned int maxel, i; //max elements, and loop index
838 	char buffer[256]; //reading buffer
839 	const char *cbuffer;
840 	const char *coma=";"; //output string variable separator
841 	int ibuffer, ssize; //value int buffer
842 	char *dataName, *dataTypeName, *dataValueString; //name of variable, type of variable, value of variable
843 	int dataType, st; //internale variable type
844 	//initialize values
845 	dataValueString = malloc(1);
846 	dataTypeName = malloc(1);
847 	memset(dataValueString, 0, 1);
848 	memset(dataTypeName, 0, 1);
849 	varindex = 0;
850 	varcounter = 0;
851 	//open and read configuration file
852 	config_init(&cfg);
853 	if(!config_read_file(&cfg, configFile)) {
854   		config_destroy(&cfg);
855 		if(optflags.quiet == 0) printf(gettext("ERROR! Can't read configuration file.\n"));
856   		return 1;
857  	};
858 	//now find variable element of given path
859 	if(dataPath == NULL) {
860 		//if path not givne load root element (default)
861 		setting = config_root_setting(&cfg);
862 	} else {
863 		setting = config_lookup(&cfg, dataPath);
864 	};
865 	if(setting == NULL) {
866   		config_destroy(&cfg);
867 		if(optflags.quiet == 0) printf(gettext("ERROR! Given variable path not found.\n"));
868   		return 3;
869  	};
870 	//read variable name
871 	dataName = config_setting_name(setting);
872 	if(dataName == NULL) dataName = "NULL"; //in case variable have no name convert to string representation
873 	//read variable type
874 	dataType = config_setting_type(setting);
875 	//next conver type to human readable and read variable value based on his type
876 	//and in cases in type not scalar read index and coutn variables
877 	switch(dataType) {
878 		case CONFIG_TYPE_INT:
879 			dataTypeName = (char*)realloc(dataTypeName, 4*sizeof(char));
880 			strcpy(dataTypeName, "int");
881 			sprintf(buffer, "%d", config_setting_get_int(setting));
882 			dataValueString = (char*)realloc(dataValueString, (strlen(buffer)+1)*sizeof(char));
883 			strcpy(dataValueString, buffer);
884 			break;
885 		case CONFIG_TYPE_INT64:
886 			dataTypeName = (char*)realloc(dataTypeName, 6*sizeof(char));
887 			strcpy(dataTypeName, "int64");
888 			sprintf(buffer, "%lld", config_setting_get_int64(setting));
889 			dataValueString = (char*)realloc(dataValueString, (strlen(buffer)+1)*sizeof(char));
890 			strcpy(dataValueString, buffer);
891 			break;
892 		case CONFIG_TYPE_FLOAT:
893 			dataTypeName = (char*)realloc(dataTypeName, 9*sizeof(char));
894 			strcpy(dataTypeName, "float");
895 			sprintf(buffer, "%f", config_setting_get_float(setting));
896 			dataValueString = (char*)realloc(dataValueString, (strlen(buffer)+1)*sizeof(char));
897 			strcpy(dataValueString, buffer);
898 			break;
899 		case CONFIG_TYPE_STRING:
900 			dataTypeName = (char*)realloc(dataTypeName, 7*sizeof(char));
901 			strcpy(dataTypeName, "string");
902 			cbuffer = config_setting_get_string(setting);
903 			dataValueString = (char*)realloc(dataValueString, (strlen(cbuffer)+1)*sizeof(char));
904 			strcpy(dataValueString, cbuffer);
905 			break;
906 		case CONFIG_TYPE_BOOL:
907 			dataTypeName = (char*)realloc(dataTypeName, 5*sizeof(char));
908 			strcpy(dataTypeName, "bool");
909 			if(optflags.boolstring == 1) {
910 				//if expect bool as string, convert it to human readable
911 				ibuffer = config_setting_get_bool(setting);
912 				if(ibuffer == CONFIG_TRUE) {
913 					dataValueString = (char*)realloc(dataValueString, 5*sizeof(char));
914 					strcpy(dataValueString, "true");
915 				} else {
916 					dataValueString = (char*)realloc(dataValueString, 6*sizeof(char));
917 					strcpy(dataValueString, "false");
918 				}
919 			} else {
920 					//else output as digit
921 					sprintf(buffer, "%d", config_setting_get_bool(setting));
922 					dataValueString = (char*)realloc(dataValueString, (strlen(buffer)+1)*sizeof(char));
923 					strcpy(dataValueString, buffer);
924 			};
925 			break;
926 		case CONFIG_TYPE_ARRAY:
927 			dataTypeName = (char*)realloc(dataTypeName, 6*sizeof(char));
928 			strcpy(dataTypeName, "array");
929 			//get element count
930 			maxel = (unsigned int)config_setting_length(setting);
931 			comaset = 0;
932 			//and loop over all elements
933 			for(i = 0; i < maxel; i++) {
934 				//get element
935 				ss = config_setting_get_elem(setting, i);
936 				if(ss != NULL) {
937 					st = config_setting_type(ss);
938 					switch(st) {
939 						case CONFIG_TYPE_INT:
940 							sprintf(buffer, "%d", config_setting_get_int(ss));
941 							dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+strlen(buffer)+2)*sizeof(char));
942 							if(comaset == 1) strcat(dataValueString, coma);
943 							strcat(dataValueString, buffer);
944 						break;
945 						case CONFIG_TYPE_INT64:
946 							sprintf(buffer, "%lld", config_setting_get_int64(ss));
947 							dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+strlen(buffer)+2)*sizeof(char));
948 							if(comaset == 1) strcat(dataValueString, coma);
949 							strcat(dataValueString, buffer);
950 						break;
951 						case CONFIG_TYPE_FLOAT:
952 							sprintf(buffer, "%f", config_setting_get_float(ss));
953 							dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+strlen(buffer)+2)*sizeof(char));
954 							if(comaset == 1) strcat(dataValueString, coma);
955 							strcat(dataValueString, buffer);
956 						break;
957 						case CONFIG_TYPE_STRING:
958 							ssize = (int)strlen(config_setting_get_string(ss));
959 
960 							dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+ssize+2)*sizeof(char));
961 							if(comaset == 1) strcat(dataValueString, coma);
962 							strcat(dataValueString, config_setting_get_string(ss));
963 						break;
964 						case CONFIG_TYPE_BOOL:
965 							if(optflags.boolstring == 1) {
966 								ibuffer = config_setting_get_bool(ss);
967 								if(ibuffer == CONFIG_TRUE) {
968 									//if bool must be outputed as humen readable - convert it
969 									dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+4+2)*sizeof(char));
970 									if(comaset == 1) strcat(dataValueString, coma);
971 									strcat(dataValueString, "true");
972 								} else {
973 									dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+5+2)*sizeof(char));
974 									if(comaset == 1) strcat(dataValueString, coma);
975 									strcat(dataValueString, "false");
976 								}
977 							} else {
978 								//else output as digit
979 								sprintf(buffer, "%d", config_setting_get_bool(ss));
980 								dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+strlen(buffer)+2)*sizeof(char));
981 								if(comaset == 1) strcat(dataValueString, coma);
982 								strcat(dataValueString, buffer);
983 							};
984 						break;
985 						case CONFIG_TYPE_ARRAY:
986 								//if array contains array output as kwyword ARRAY
987 								dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+7)*sizeof(char));
988 								if(comaset == 1) strcat(dataValueString, coma);
989 								strcat(dataValueString, "ARRAY");
990 						break;
991 						case CONFIG_TYPE_LIST:
992 								//if array contains list output as keyword LIST
993 								dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+6)*sizeof(char));
994 								if(comaset == 1) strcat(dataValueString, coma);
995 								strcat(dataValueString, "LIST");
996 						break;
997 						case CONFIG_TYPE_GROUP:
998 								//if array contains group output as keywort GROUP
999 								dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+7)*sizeof(char));
1000 								if(comaset == 1) strcat(dataValueString, coma);
1001 								strcat(dataValueString, "GROUP");
1002 						break;
1003 					};
1004 					comaset = 1;
1005 				};
1006 			};
1007 			break;
1008 		case CONFIG_TYPE_LIST:
1009 			dataTypeName = (char*)realloc(dataTypeName, 5*sizeof(char));
1010 			strcpy(dataTypeName, "list");
1011 			//get element count
1012 			maxel = (unsigned int)config_setting_length(setting);
1013 			//end loop over all elements
1014 			comaset = 0;
1015 			for(i = 0; i < maxel; i++) {
1016 				ss = config_setting_get_elem(setting, i);
1017 				if(ss != NULL) {
1018 					st = config_setting_type(ss);
1019 					switch(st) {
1020 						case CONFIG_TYPE_INT:
1021 							sprintf(buffer, "%d", config_setting_get_int(ss));
1022 							dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+strlen(buffer)+2)*sizeof(char));
1023 							if(comaset == 1) strcat(dataValueString, coma);
1024 							strcat(dataValueString, buffer);
1025 						break;
1026 						case CONFIG_TYPE_INT64:
1027 							sprintf(buffer, "%lld", config_setting_get_int64(ss));
1028 							dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+strlen(buffer)+2)*sizeof(char));
1029 							if(comaset == 1) strcat(dataValueString, coma);
1030 							strcat(dataValueString, buffer);
1031 						break;
1032 						case CONFIG_TYPE_FLOAT:
1033 							sprintf(buffer, "%f", config_setting_get_float(ss));
1034 							dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+strlen(buffer)+2)*sizeof(char));
1035 							if(comaset == 1) strcat(dataValueString, coma);
1036 							strcat(dataValueString, buffer);
1037 						break;
1038 						case CONFIG_TYPE_STRING:
1039 							ssize = (int)strlen(config_setting_get_string(ss));
1040 
1041 							dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+ssize+2)*sizeof(char));
1042 							if(comaset == 1) strcat(dataValueString, coma);
1043 							strcat(dataValueString, config_setting_get_string(ss));
1044 						break;
1045 						case CONFIG_TYPE_BOOL:
1046 							if(optflags.boolstring == 1) {
1047 								ibuffer = config_setting_get_bool(ss);
1048 								if(ibuffer == CONFIG_TRUE) {
1049 									//if bool must be printout as humanreadable - convert it
1050 									dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+4+2)*sizeof(char));
1051 									if(comaset == 1) strcat(dataValueString, coma);
1052 									strcat(dataValueString, "true");
1053 								} else {
1054 									dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+5+2)*sizeof(char));
1055 									if(comaset == 1) strcat(dataValueString, coma);
1056 									strcat(dataValueString, "false");
1057 								}
1058 							} else {
1059 								//else output as int
1060 								sprintf(buffer, "%d", config_setting_get_bool(ss));
1061 								dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+strlen(buffer)+2)*sizeof(char));
1062 								if(comaset == 1) strcat(dataValueString, coma);
1063 								strcat(dataValueString, buffer);
1064 							};
1065 						break;
1066 						case CONFIG_TYPE_ARRAY:
1067 								//if list contain array output as keyword ARRAY
1068 								dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+7)*sizeof(char));
1069 								if(comaset == 1) strcat(dataValueString, coma);
1070 								strcat(dataValueString, "ARRAY");
1071 						break;
1072 						case CONFIG_TYPE_LIST:
1073 								//if list contain list output as keyword LIST
1074 								dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+6)*sizeof(char));
1075 								if(comaset == 1) strcat(dataValueString, coma);
1076 								strcat(dataValueString, "LIST");
1077 						break;
1078 						case CONFIG_TYPE_GROUP:
1079 								//if list contain group output as keyword GROUP
1080 								dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+7)*sizeof(char));
1081 								if(comaset == 1) strcat(dataValueString, coma);
1082 								strcat(dataValueString, "GROUP");
1083 						break;
1084 					};
1085 					comaset = 1;
1086 				};
1087 			};
1088 			break;
1089 		case CONFIG_TYPE_GROUP:
1090 			dataTypeName = (char*)realloc(dataTypeName, 6*sizeof(char));
1091 			strcpy(dataTypeName, "group");
1092 			//get elementc count
1093 			maxel = (unsigned int)config_setting_length(setting);
1094 			//and loop over all elements
1095 			//but in group case, we return inside variables names
1096 			comaset = 0;
1097 			for(i = 0; i < maxel; i++) {
1098 				ss = config_setting_get_elem(setting, i);
1099 				if(ss != NULL) {
1100 					ssize = (int)strlen(config_setting_name(ss));
1101 					dataValueString = (char*)realloc(dataValueString, (strlen(dataValueString)+ssize+2)*sizeof(char));
1102 					if(comaset == 1) strcat(dataValueString, coma);
1103 					strcat(dataValueString, config_setting_name(ss));
1104 					comaset = 1;
1105 				};
1106 			};
1107 			break;
1108 	};
1109 
1110 	//last we get readed variable index, and element count
1111 	varindex = config_setting_index(setting);
1112 	varcounter = config_setting_length(setting);
1113 
1114 	//and finaly output data
1115 	if(optflags.names == 1 && optflags.quiet == 0) printf(gettext("Variable name:           %s\n"), dataName);
1116 	if(optflags.names == 1 && optflags.quiet == 1) printf("%s", dataName);
1117 	if((optflags.types == 1 && optflags.quiet == 1) && optflags.names == 1) printf(":");
1118 	if(optflags.types == 1 && optflags.quiet == 0) printf(gettext("Variable type:           %s\n"), dataTypeName);
1119 	if(optflags.types == 1 && optflags.quiet == 1) printf("%s", dataTypeName);
1120 	if((optflags.values == 1 && optflags.quiet == 1) && (optflags.names == 1 || optflags.types == 1)) printf(":");
1121 	if(optflags.values == 1 && optflags.quiet == 0) printf(gettext("Variable value:          %s\n"), dataValueString);
1122 	if(optflags.values == 1 && optflags.quiet == 1) printf("%s", dataValueString);
1123 	if((optflags.indexes == 1 && optflags.quiet == 1) && (optflags.names == 1 || optflags.types == 1 || optflags.values == 1)) printf(":");
1124 	if(optflags.indexes == 1 && optflags.quiet == 0) printf(gettext("Variable index:          %d\n"), varindex);
1125 	if(optflags.indexes == 1 && optflags.quiet == 1) printf("%d", varindex);
1126 	if((optflags.counter == 1 && optflags.quiet == 1) && (optflags.names == 1 || optflags.types == 1 || optflags.values == 1 || optflags.indexes == 1)) printf(":");
1127 	if(optflags.counter == 1 && optflags.quiet == 0) printf(gettext("Variable elements count: %d\n"), varcounter);
1128 	if(optflags.counter == 1 && optflags.quiet == 1) printf("%d", varcounter);
1129 	if(optflags.quiet == 1) printf("\n");
1130 
1131 	config_destroy(&cfg);
1132 	return 0;
1133 }
1134 
main(int argc,char ** argv)1135 int main(int argc, char **argv) {
1136 	//firs set locale and domain to work with internationalization
1137 	setlocale(LC_ALL, "");
1138 	bindtextdomain("ls-config", "/usr/share/locale");
1139 	textdomain("ls-config");
1140 
1141 	//then declare and init values
1142    int opt,test; //used for read innput: option, and testing
1143 	int fd; //file descriptor
1144 	char *sinp, *dataPath=NULL, *dataString=NULL, *dataType=NULL; //string input, configuration variable path, input data, variable type
1145 	char *configFile=NULL; //config file name (with path)
1146    struct flags optflags = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //global flags initialize
1147 	int excode; //program exit code
1148 	excode = 0;
1149 
1150 	sinp = malloc(sizeof(char) * 256);
1151 
1152 	//long options reading
1153 	struct option long_options[] = {
1154 		/* These options set a flag. */
1155 		{"quiet",   no_argument, &optflags.quiet, 1},
1156 		{"names",   no_argument, &optflags.names, 1},
1157 		{"types",   no_argument, &optflags.types, 1},
1158 		{"values",   no_argument, &optflags.values, 1},
1159 		{"indexes",   no_argument, &optflags.indexes, 1},
1160 		{"count",   no_argument, &optflags.counter, 1},
1161 		{"unset",   no_argument, &optflags.unset, 1},
1162 		{"bool-string",   no_argument, &optflags.boolstring, 1},
1163 		/* These options don't set a flag.
1164 		 We distinguish them by their indices. */
1165 		{"help", no_argument, 0, 'h'},
1166 		{"set",  required_argument, 0, 's'},
1167 		{"get",  optional_argument, 0, 'g'},
1168 		{"data", required_argument, 0, 'd'},
1169 		{"type", required_argument, 0, 'p'},
1170 		{"file", required_argument, 0, 'f'},
1171 		{0, 0, 0, 0}
1172 	};
1173 
1174 	//next collect all input (given as options to program)
1175 	while(1) {
1176 		int option_index = 0;
1177 		opt = getopt_long (argc, argv, "qntvicubs:g:d:p:hf:", long_options, &option_index);
1178 
1179 		if(opt == -1) break;
1180 
1181 		switch (opt) {
1182 			case 0:
1183 				/* If this option set a flag, do nothing else now. */
1184 				if(long_options[option_index].flag != 0) break;
1185 				if(strcmp(long_options[option_index].name, "set") == 0 && optarg) {
1186 					test = sscanf(optarg, "%s", sinp);
1187 					if(test > 0) {
1188 						dataPath = (char*)malloc((strlen(sinp)+1)*sizeof(char));
1189 						strcpy(dataPath, sinp);
1190 					};
1191 					optflags.mode = 1;
1192 				};
1193 				if(strcmp(long_options[option_index].name, "get") == 0 && optarg) {
1194 					test = sscanf(optarg, "%s", sinp);
1195 					if(test > 0) {
1196 						dataPath = (char*)malloc((strlen(sinp)+1)*sizeof(char));
1197 						strcpy(dataPath, sinp);
1198 					};
1199 					optflags.mode = 0;
1200 				};
1201 				if(strcmp(long_options[option_index].name, "data") == 0 && optarg) {
1202 					test = sscanf(optarg, "%[^\n]s", sinp);
1203 					if(test > 0) {
1204 						dataString = (char*)malloc((strlen(sinp)+1)*sizeof(char));
1205 						strcpy(dataString, sinp);
1206 					};
1207 				};
1208 				if(strcmp(long_options[option_index].name, "type") == 0 && optarg) {
1209 					test = sscanf(optarg, "%s", sinp);
1210 					if(test > 0) {
1211 						dataType = (char*)malloc((strlen(sinp)+1)*sizeof(char));
1212 						strcpy(dataType, sinp);
1213 					};
1214 				};
1215 				if(strcmp(long_options[option_index].name, "file") == 0 && optarg) {
1216 					test = sscanf(optarg, "%[^\n]s", sinp);
1217 					if(test > 0) {
1218 						configFile = (char*)malloc((strlen(sinp)+1)*sizeof(char));
1219 						strcpy(configFile, sinp);
1220 					};
1221 				};
1222 				break;
1223 			case 'q':
1224 				optflags.quiet = 1;
1225 				break;
1226 			case 'n':
1227 				optflags.names = 1;
1228 				break;
1229 			case 't':
1230 				optflags.types = 1;
1231 				break;
1232 			case 'v':
1233 				optflags.values = 1;
1234 				break;
1235 			case 'i':
1236 				optflags.indexes = 1;
1237 				break;
1238 			case 'c':
1239 				optflags.counter = 1;
1240 				break;
1241 			case 'u':
1242 				optflags.unset = 1;
1243 				break;
1244 			case 'b':
1245 				optflags.boolstring = 1;
1246 				break;
1247 			case 's':
1248 				if(optarg) {
1249 					test = sscanf(optarg, "%s", sinp);
1250 					if(test > 0) {
1251 						dataPath = (char*)malloc((strlen(sinp)+1)*sizeof(char));
1252 						strcpy(dataPath, sinp);
1253 					};
1254 					optflags.mode = 1;
1255 				};
1256 				break;
1257 			case 'g':
1258 				if(optarg) {
1259 					test = sscanf(optarg, "%s", sinp);
1260 					if(test > 0) {
1261 						dataPath = (char*)malloc((strlen(sinp)+1)*sizeof(char));
1262 						strcpy(dataPath, sinp);
1263 					};
1264 				};
1265 				optflags.mode = 0;
1266 				break;
1267 			case 'd':
1268 				if(optarg) {
1269 					test = sscanf(optarg, "%[^\n]s", sinp);
1270 					if(test > 0) {
1271 						dataString = (char*)malloc((strlen(sinp)+1)*sizeof(char));
1272 						strcpy(dataString, sinp);
1273 					};
1274 				};
1275 				break;
1276 			case 'p':
1277 				if(optarg) {
1278 					test = sscanf(optarg, "%s", sinp);
1279 					if(test > 0) {
1280 						dataType = (char*)malloc((strlen(sinp)+1)*sizeof(char));
1281 						strcpy(dataType, sinp);
1282 					};
1283 				};
1284 				break;
1285 			case 'h':
1286 				//free input buffer and printout help message
1287 				free(sinp);
1288 				printHelp(); //this function contain exit from program
1289 				break;
1290 			case 'f':
1291 				test = sscanf(optarg, "%[^\n]s", sinp);
1292 				if(test > 0) {
1293 					configFile = (char*)malloc((strlen(sinp)+1)*sizeof(char));
1294 					strcpy(configFile, sinp);
1295 				};
1296 				break;
1297 			case '?':
1298 				break;
1299 			default:
1300 				break;
1301 		}
1302 	};
1303 
1304 	//first of all we must ensure, then configuration file are available with right access mode
1305 	if(optflags.mode == 0 && access(configFile, R_OK) < 0) optflags.error = 1;
1306 	if(optflags.mode == 1) {
1307 		fd = open(configFile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1308 		if(fd < 0) {
1309 			optflags.error = 1;
1310  		};
1311 		close(fd);
1312    };
1313 	if(optflags.error > 0) {
1314 		if(optflags.quiet == 0) printf(gettext("ERROR! Can't read configuration file.\n"));
1315 		free(sinp);
1316 		free(configFile);
1317 		exit(1);
1318    };
1319 
1320 	//now if we want to set variable, we must have his path
1321    if(optflags.mode == 1 && dataPath == NULL) {
1322 		if(optflags.quiet == 0) printf(gettext("ERROR! Conviguration variable path not given.\n"));
1323 		free(sinp);
1324 		free(configFile);
1325 		exit(4);
1326    };
1327 
1328 	//if no output data requested, set to default output
1329 	if(optflags.names == 0 && optflags.types == 0 && optflags.values == 0 && optflags.indexes == 0 && optflags.counter == 0) {
1330 		optflags.names = 1;
1331 		optflags.types = 1;
1332 		optflags.values = 1;
1333 	};
1334 
1335 	//now we invode main work of this software based on request type (set, unset of get)
1336 	if(optflags.mode == 0) excode = read_config(configFile, dataPath, optflags);
1337 	if(optflags.mode == 1 && optflags.unset == 1) excode = unset_config(configFile, dataPath, optflags);
1338 	if(optflags.mode == 1 && optflags.unset == 0) excode = set_config(configFile, dataPath, optflags, dataString, dataType);
1339 
1340 	//then finalize free resources and exit returnig excode
1341 	free(sinp);
1342 	free(configFile);
1343 	exit(excode);
1344 }
1345 
1346