1 /*
2 * SNOOPY LOGGER
3 *
4 * File: configfile.c
5 *
6 * Copyright (c) 2014-2015 Bostjan Skufca <bostjan@a2o.si>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23
24
25 /*
26 * Includes order: from local to global
27 */
28 #include "configfile.h"
29
30 #include "snoopy.h"
31 #include "configfile.h"
32 #include "configuration.h"
33 #include "misc.h"
34 #include "outputregistry.h"
35
36 #include "lib/inih/src/ini.h"
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/types.h>
42 #include <unistd.h>
43
44
45
46 /*
47 * snoopy_configfile_load_file
48 *
49 * Description:
50 * Parses INI configuration file and overrides Snoopy
51 * configuration with changed values.
52 *
53 * Params:
54 * file Path log INI configuration file
55 *
56 * Return:
57 * int 0 on success, -1 on error openinf file, other int for other errors
58 */
snoopy_configfile_load(char * iniFilePath)59 int snoopy_configfile_load (
60 char *iniFilePath
61 ) {
62 int iniParseStatus;
63 snoopy_configuration_t *CFG;
64
65
66 /* Get config pointer */
67 CFG = snoopy_configuration_get();
68
69
70 /* Tell Snoopy we are using configuration file */
71 CFG->configfile_path = iniFilePath;
72
73 /* Parse the INI configuration file first */
74 iniParseStatus = ini_parse(iniFilePath, snoopy_configfile_parser_callback, CFG);
75 if (0 != iniParseStatus) {
76 return -1;
77 }
78 CFG->configfile_found = SNOOPY_TRUE;
79
80
81 /* Housekeeping */
82 CFG->configfile_parsed = SNOOPY_TRUE; // We have successfully parsed configuration file
83 return 0;
84 }
85
86
87
88
89 /*
90 * snoopy_configfile_parser_callback
91 *
92 * Description:
93 * Callback function for each found ini value in parsed config file.
94 *
95 * Params:
96 * ...
97 *
98 * Return:
99 * ...
100 */
snoopy_configfile_parser_callback(void * sth,const char * section,const char * name,const char * confValString)101 int snoopy_configfile_parser_callback (
102 void* sth,
103 const char* section,
104 const char* name,
105 const char* confValString
106 ) {
107 int confValInt;
108
109
110 /* Qualify pointer? */
111 snoopy_configuration_t* CFG = (snoopy_configuration_t*)sth;
112
113
114 /* Skip unknown sections */
115 if (0 != strcmp(section, "snoopy")) {
116 return 1;
117 }
118
119
120
121 /* Do the name matching */
122 #define MATCHNAME(n) strcmp(name, n) == 0
123
124
125 if (MATCHNAME("error_logging")) {
126 confValInt = snoopy_configfile_getboolean(confValString, -1);
127 if (-1 != confValInt) {
128 CFG->error_logging_enabled = confValInt;
129 }
130 return 1;
131 }
132
133
134 if (MATCHNAME("message_format")) {
135 CFG->message_format = strdup(confValString);
136 CFG->message_format_malloced = SNOOPY_TRUE;
137 return 1;
138 }
139
140
141 if (MATCHNAME("filter_chain")) {
142 CFG->filter_chain = strdup(confValString);
143 CFG->filter_chain_malloced = SNOOPY_TRUE;
144 return 1;
145 }
146
147
148 if (MATCHNAME("output")) {
149 snoopy_configfile_parse_output(confValString);
150 return 1;
151 }
152
153
154 if (MATCHNAME("syslog_facility")) {
155 snoopy_configfile_parse_syslog_facility(confValString);
156 return 1;
157 }
158
159
160 if (MATCHNAME("syslog_ident")) {
161 CFG->syslog_ident = strdup(confValString);
162 CFG->syslog_ident_malloced = SNOOPY_TRUE;
163 return 1;
164 }
165
166
167 if (MATCHNAME("syslog_level")) {
168 snoopy_configfile_parse_syslog_level(confValString);
169 return 1;
170 }
171
172
173 /* Why are we returning 1 instead of zero everywhere? */
174 return 1;
175 }
176
177
178
179 /*
180 * snoopy_configfile_parse_output
181 *
182 * Description:
183 * Parses configuration setting syslog_output and
184 * sets appropriate internal configuration variable(s).
185 * Uses default setting if unknown value.
186 *
187 * Params:
188 * confVal Value from configuration file
189 *
190 * Return:
191 * void
192 */
snoopy_configfile_parse_output(const char * confValOrig)193 void snoopy_configfile_parse_output (
194 const char *confValOrig
195 ) {
196 char *confVal;
197 const char * outputName;
198 const char * outputArg;
199 int outputArgFound = SNOOPY_FALSE;
200 snoopy_configuration_t *CFG;
201
202
203 /* Get config pointer */
204 CFG = snoopy_configuration_get();
205
206
207 // Do not assign null to it explicitly, as you get "Explicit null dereference" Coverity error.
208 // If you do not assign it, Coverity complains with "Uninitialized pointer read".
209 char *saveptr1 = "";
210
211 // First clone the config value, as it gets freed by ini parsing library
212 confVal = strdup(confValOrig);
213
214 // Check if configured value contains argument(s)
215 if (NULL == strchr(confVal, ':')) {
216 outputName = confVal;
217 CFG->output_arg = "";
218 CFG->output_arg_malloced = SNOOPY_FALSE;
219 outputArg = "";
220 } else {
221 // Separate output name from its arguments
222 outputName = strtok_r(confVal, ":", &saveptr1);
223 outputArg = strtok_r(NULL , ":", &saveptr1);
224 outputArgFound = SNOOPY_TRUE;
225
226 }
227
228 // Determine output name
229 if (SNOOPY_TRUE == snoopy_outputregistry_doesNameExist(outputName)) {
230 CFG->output = strdup(outputName);
231 CFG->output_malloced = SNOOPY_TRUE;
232
233 if (SNOOPY_TRUE == outputArgFound) {
234 // THINK What if conf.output_arg was set in previous call to this function,
235 // and is already malloced? We need to detect that and free previous
236 // allocation.
237 CFG->output_arg = strdup(outputArg);
238 CFG->output_arg_malloced = SNOOPY_TRUE;
239 }
240 } else {
241 CFG->output = SNOOPY_OUTPUT_DEFAULT;
242 CFG->output_malloced = SNOOPY_FALSE;
243 CFG->output_arg = SNOOPY_OUTPUT_DEFAULT_ARG;
244 CFG->output_arg_malloced = SNOOPY_FALSE;
245 }
246
247 // Housekeeping
248 free(confVal);
249 }
250
251
252
253 /*
254 * snoopy_configfile_parse_syslog_facility
255 *
256 * Description:
257 * Parses configuration setting syslog_facility and
258 * sets appropriate config variable.
259 * Uses default setting if unknown value.
260 *
261 * Params:
262 * confVal Value from configuration file
263 *
264 * Return:
265 * void
266 */
snoopy_configfile_parse_syslog_facility(const char * confValOrig)267 void snoopy_configfile_parse_syslog_facility (
268 const char *confValOrig
269 ) {
270 char *confVal;
271 const char *confValCleaned;
272 int facilityInt;
273 snoopy_configuration_t *CFG;
274
275
276 /* Get config pointer */
277 CFG = snoopy_configuration_get();
278
279 // Duplicate the ini value, as we need to modify it
280 confVal = strdup(confValOrig);
281
282 // First cleanup the value
283 confValCleaned = snoopy_configfile_syslog_value_cleanup(confVal);
284
285 // Evaluate and set configuration flag
286 facilityInt = snoopy_syslog_convert_facilityToInt(confValCleaned);
287 if (-1 == facilityInt) {
288 CFG->syslog_facility = SNOOPY_SYSLOG_FACILITY;
289 } else {
290 CFG->syslog_facility = facilityInt;
291 }
292
293 /* Housekeeping */
294 free(confVal);
295 }
296
297
298
299 /*
300 * snoopy_configfile_parse_syslog_level
301 *
302 * Description:
303 * Parses configuration setting syslog_level and
304 * sets appropriate config variable.
305 * Uses default setting if unknown value.
306 *
307 * Params:
308 * confVal Value from configuration file
309 *
310 * Return:
311 * void
312 */
snoopy_configfile_parse_syslog_level(const char * confValOrig)313 void snoopy_configfile_parse_syslog_level (
314 const char *confValOrig
315 ) {
316 char *confVal;
317 const char *confValCleaned;
318 int levelInt;
319 snoopy_configuration_t *CFG;
320
321
322 /* Get config pointer */
323 CFG = snoopy_configuration_get();
324
325 // Duplicate the ini value, as we need to modify it
326 confVal = strdup(confValOrig);
327
328 // First cleanup the value
329 confValCleaned = snoopy_configfile_syslog_value_cleanup(confVal);
330
331 // Evaluate and set configuration flag
332 levelInt = snoopy_syslog_convert_levelToInt(confValCleaned);
333 if (-1 == levelInt) {
334 CFG->syslog_level = SNOOPY_SYSLOG_LEVEL;
335 } else {
336 CFG->syslog_level = levelInt;
337 }
338
339 /* Housekeeping */
340 free(confVal);
341 }
342
343
344
345 /*
346 * snoopy_configfile_syslog_value_cleanup
347 *
348 * Description:
349 * Convert existing string to upper case, and remove LOG_ prefix
350 *
351 * Params:
352 * confVal Pointer to string to change and to be operated on
353 *
354 * Return:
355 * char * Pointer to cleaned string (either the same as initial argument,
356 * or 4 characters advanced, to remove LOG_ prefix
357 */
snoopy_configfile_syslog_value_cleanup(char * confVal)358 char *snoopy_configfile_syslog_value_cleanup (char *confVal)
359 {
360 char *confValCleaned;
361
362 // Convert to upper case
363 snoopy_configfile_strtoupper(confVal);
364
365 // Remove LOG_ prefix
366 confValCleaned = snoopy_configfile_syslog_value_remove_prefix(confVal);
367
368 return confValCleaned;
369 }
370
371
372
373 /*
374 * snoopy_configfile_syslog_value_remove_prefix
375 *
376 * Description:
377 * Remove the LOG_ prefix, return pointer to new string (either equal
378 * or +4 chars advanced)
379 *
380 * Params:
381 * string Pointer to string to remove LOG_ prefix
382 *
383 * Return:
384 * char * Pointer to non LOG_ part of the string
385 */
snoopy_configfile_syslog_value_remove_prefix(char * confVal)386 char *snoopy_configfile_syslog_value_remove_prefix (char *confVal)
387 {
388 if (0 == strncmp(confVal, "LOG_", 4)) {
389 return confVal+4;
390 } else {
391 return confVal;
392 }
393 }
394
395
396
397 /*
398 * snoopy_configfile_strtoupper
399 *
400 * Description:
401 * Convert existing string to upper case
402 *
403 * Params:
404 * string Pointer to string to change and to be operated on
405 *
406 * Return:
407 * void
408 */
snoopy_configfile_strtoupper(char * s)409 void snoopy_configfile_strtoupper (char *s)
410 {
411 while (*s) {
412 if ((*s >= 'a' ) && (*s <= 'z')) {
413 *s -= ('a'-'A');
414 }
415 s++;
416 }
417 }
418
419
420
421 /*-------------------------------------------------------------------------*/
422 /**
423 @origin Literally copy-pasted from ndevilla's iniparser
424
425
426 @brief Get the string associated to a key, convert to a boolean
427 @param d Dictionary to search
428 @param key Key string to look for
429 @param notfound Value to return in case of error
430 @return integer
431
432 This function queries a dictionary for a key. A key as read from an
433 ini file is given as "section:key". If the key cannot be found,
434 the notfound value is returned.
435
436 A true boolean is found if one of the following is matched:
437
438 - A string starting with 'y'
439 - A string starting with 'Y'
440 - A string starting with 't'
441 - A string starting with 'T'
442 - A string starting with '1'
443
444 A false boolean is found if one of the following is matched:
445
446 - A string starting with 'n'
447 - A string starting with 'N'
448 - A string starting with 'f'
449 - A string starting with 'F'
450 - A string starting with '0'
451
452 The notfound value returned if no boolean is identified, does not
453 necessarily have to be 0 or 1.
454 */
455 /*--------------------------------------------------------------------------*/
snoopy_configfile_getboolean(const char * c,int notfound)456 int snoopy_configfile_getboolean (const char *c, int notfound)
457 {
458 int ret;
459
460 if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
461 ret = 1 ;
462 } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
463 ret = 0 ;
464 } else {
465 ret = notfound ;
466 }
467 return ret;
468 }
469