]> git.proxmox.com Git - mirror_corosync.git/blame - exec/logconfig.c
config: Don't free pointers used by transports
[mirror_corosync.git] / exec / logconfig.c
CommitLineData
7b2ddfa4
SD
1/*
2 * Copyright (c) 2002-2005 MontaVista Software, Inc.
8a45e2b1 3 * Copyright (c) 2006-2011 Red Hat, Inc.
7b2ddfa4
SD
4 *
5 * All rights reserved.
6 *
46b01638 7 * Author: Steven Dake (sdake@redhat.com)
8a45e2b1 8 * Jan Friesse (jfriesse@redhat.com)
7b2ddfa4
SD
9 *
10 * This software licensed under BSD license, the text of which follows:
3568f266 11 *
7b2ddfa4
SD
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * - Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above copyright notice,
18 * this list of conditions and the following disclaimer in the documentation
19 * and/or other materials provided with the distribution.
20 * - Neither the name of the MontaVista Software, Inc. nor the names of its
21 * contributors may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34 * THE POSSIBILITY OF SUCH DAMAGE.
35 */
031c02f5 36
b283ef8f
FDN
37#include "config.h"
38
e1f53138 39#include <corosync/totem/totem.h>
8ad583a5 40#include <corosync/logsys.h>
f008cf44 41#ifdef LOGCONFIG_USE_ICMAP
7e1c9771 42#include <corosync/icmap.h>
b283ef8f
FDN
43#define MAP_KEYNAME_MAXLEN ICMAP_KEYNAME_MAXLEN
44#define map_get_string(key_name, value) icmap_get_string(key_name, value)
45#else
46#include <corosync/cmap.h>
47static cmap_handle_t cmap_handle;
48static const char *main_logfile;
49#define MAP_KEYNAME_MAXLEN CMAP_KEYNAME_MAXLEN
50#define map_get_string(key_name, value) cmap_get_string(cmap_handle, key_name, value)
51#endif
e1f53138 52
7b2ddfa4 53#include "util.h"
f008cf44 54#include "logconfig.h"
7b2ddfa4 55
7b2ddfa4 56static char error_string_response[512];
bc87f196 57
84f5c3b6
FDN
58/**
59 * insert_into_buffer
60 * @target_buffer: a buffer where to write results
61 * @bufferlen: tell us the size of the buffer to avoid overflows
62 * @entry: entry that needs to be added to the buffer
63 * @after: can either be NULL or set to a string.
64 * if NULL, @entry is prependend to logsys_format_get buffer.
65 * if set, @entry is added immediately after @after.
66 *
67 * Since the function is specific to logsys_format_get handling, it is implicit
68 * that source is logsys_format_get();
69 *
70 * In case of failure, target_buffer could be left dirty. So don't trust
71 * any data leftover in it.
72 *
73 * Searching for "after" assumes that there is only entry of "after"
74 * in the source. Afterall we control the string here and for logging format
75 * it makes little to no sense to have duplicate format entries.
76 *
77 * Returns: 0 on success, -1 on failure
78 **/
79static int insert_into_buffer(
80 char *target_buffer,
81 size_t bufferlen,
82 const char *entry,
83 const char *after)
84{
85 const char *current_format = NULL;
86
87 current_format = logsys_format_get();
88
89 /* if the entry is already in the format we don't add it again */
90 if (strstr(current_format, entry) != NULL) {
91 return -1;
92 }
93
94 /* if there is no "after", simply prepend the requested entry
95 * otherwise go for beautiful string manipulation.... </sarcasm> */
96 if (!after) {
97 if (snprintf(target_buffer, bufferlen - 1, "%s%s",
98 entry,
99 current_format) >= bufferlen - 1) {
100 return -1;
101 }
102 } else {
103 const char *afterpos;
104 size_t afterlen;
105 size_t templen;
106
107 /* check if after is contained in the format
108 * and afterlen has a meaning or return an error */
109 afterpos = strstr(current_format, after);
110 afterlen = strlen(after);
111 if ((!afterpos) || (!afterlen)) {
112 return -1;
113 }
114
115 templen = afterpos - current_format + afterlen;
116 if (snprintf(target_buffer, templen + 1, "%s", current_format)
117 >= bufferlen - 1) {
118 return -1;
119 }
120 if (snprintf(target_buffer + templen, bufferlen - ( templen + 1 ),
121 "%s%s", entry, current_format + templen)
122 >= bufferlen - ( templen + 1 )) {
123 return -1;
124 }
125 }
126 return 0;
127}
128
c3c75acf 129/*
79dba9c5 130 * format set is global specific option that
c3c75acf
FDN
131 * doesn't apply at system/subsystem level.
132 */
133static int corosync_main_config_format_set (
c3c75acf 134 const char **error_string)
7b2ddfa4 135{
c3c75acf 136 const char *error_reason;
84f5c3b6 137 char new_format_buffer[PATH_MAX];
8a45e2b1 138 char *value = NULL;
55d97fd8 139 int err = 0;
48cb28b0 140 char timestamp_str_to_add[8];
5c257afb 141
b283ef8f 142 if (map_get_string("logging.fileline", &value) == CS_OK) {
c3c75acf
FDN
143 if (strcmp (value, "on") == 0) {
144 if (!insert_into_buffer(new_format_buffer,
145 sizeof(new_format_buffer),
37e17e7a 146 " %f:%l", "g]")) {
c3c75acf 147 err = logsys_format_set(new_format_buffer);
7b2ddfa4 148 } else
c3c75acf
FDN
149 if (!insert_into_buffer(new_format_buffer,
150 sizeof(new_format_buffer),
151 "%f:%l", NULL)) {
152 err = logsys_format_set(new_format_buffer);
64a83a76 153 }
c3c75acf
FDN
154 } else
155 if (strcmp (value, "off") == 0) {
156 /* nothing to do here */
157 } else {
158 error_reason = "unknown value for fileline";
df6b87f2 159 free(value);
c3c75acf 160 goto parse_error;
64a83a76 161 }
8a45e2b1
JF
162
163 free(value);
c3c75acf 164 }
8a45e2b1 165
55d97fd8
FDN
166 if (err) {
167 error_reason = "not enough memory to set logging format buffer";
168 goto parse_error;
169 }
170
b283ef8f 171 if (map_get_string("logging.function_name", &value) == CS_OK) {
c3c75acf
FDN
172 if (strcmp (value, "on") == 0) {
173 if (!insert_into_buffer(new_format_buffer,
174 sizeof(new_format_buffer),
175 "%n:", "f:")) {
176 err = logsys_format_set(new_format_buffer);
e2d327e5 177 } else
c3c75acf
FDN
178 if (!insert_into_buffer(new_format_buffer,
179 sizeof(new_format_buffer),
37e17e7a 180 " %n", "g]")) {
c3c75acf 181 err = logsys_format_set(new_format_buffer);
64a83a76 182 }
c3c75acf
FDN
183 } else
184 if (strcmp (value, "off") == 0) {
185 /* nothing to do here */
186 } else {
187 error_reason = "unknown value for function_name";
df6b87f2 188 free(value);
c3c75acf 189 goto parse_error;
64a83a76 190 }
8a45e2b1
JF
191
192 free(value);
c3c75acf 193 }
8a45e2b1 194
55d97fd8
FDN
195 if (err) {
196 error_reason = "not enough memory to set logging format buffer";
197 goto parse_error;
198 }
199
48cb28b0
JF
200 memset(timestamp_str_to_add, 0, sizeof(timestamp_str_to_add));
201
b283ef8f 202 if (map_get_string("logging.timestamp", &value) == CS_OK) {
c3c75acf 203 if (strcmp (value, "on") == 0) {
48cb28b0 204 strcpy(timestamp_str_to_add, "%t");
bd2fff5b
JF
205#ifdef QB_FEATURE_LOG_HIRES_TIMESTAMPS
206 } else if (strcmp (value, "hires") == 0) {
48cb28b0 207 strcpy(timestamp_str_to_add, "%T");
bd2fff5b
JF
208#endif
209 } else if (strcmp (value, "off") == 0) {
c3c75acf
FDN
210 /* nothing to do here */
211 } else {
212 error_reason = "unknown value for timestamp";
df6b87f2 213 free(value);
c3c75acf 214 goto parse_error;
3568f266 215 }
8a45e2b1
JF
216
217 free(value);
48cb28b0
JF
218 } else {
219 /*
220 * Display hires timestamp by default, otherwise standard timestamp
221 */
222#ifdef QB_FEATURE_LOG_HIRES_TIMESTAMPS
223 strcpy(timestamp_str_to_add, "%T");
224#else
225 strcpy(timestamp_str_to_add, "%t");
226#endif
227 }
228
229 if(strcmp(timestamp_str_to_add, "") != 0) {
230 strcat(timestamp_str_to_add, " ");
231 if (insert_into_buffer(new_format_buffer, sizeof(new_format_buffer),
232 timestamp_str_to_add, NULL) == 0) {
233 err = logsys_format_set(new_format_buffer);
234 }
c3c75acf
FDN
235 }
236
55d97fd8
FDN
237 if (err) {
238 error_reason = "not enough memory to set logging format buffer";
239 goto parse_error;
240 }
241
c3c75acf
FDN
242 return (0);
243
244parse_error:
245 *error_string = error_reason;
246
247 return (-1);
248}
249
79dba9c5
JF
250/*
251 * blackbox is another global specific option that
252 * doesn't apply at system/subsystem level.
253 */
254static int corosync_main_config_blackbox_set (
255 const char **error_string)
256{
257 const char *error_reason;
258 char *value = NULL;
259
260 if (map_get_string("logging.blackbox", &value) == CS_OK) {
261 if (strcmp (value, "on") == 0) {
262 (void)logsys_blackbox_set(QB_TRUE);
263 } else if (strcmp (value, "off") == 0) {
264 (void)logsys_blackbox_set(QB_FALSE);
265 } else {
266 error_reason = "unknown value for blackbox";
267 free(value);
268 goto parse_error;
269 }
270
271 free(value);
272 } else {
273 (void)logsys_blackbox_set(QB_TRUE);
274 }
275
276 return (0);
277
278parse_error:
279 *error_string = error_reason;
280
281 return (-1);
282}
283
99db3567 284static int corosync_main_config_log_destination_set (
8a45e2b1
JF
285 const char *path,
286 const char *key,
99db3567
JF
287 const char *subsys,
288 const char **error_string,
99db3567
JF
289 unsigned int mode_mask,
290 char deprecated,
125848d8 291 char default_value,
99db3567
JF
292 const char *replacement)
293{
294 static char formatted_error_reason[128];
8a45e2b1 295 char *value = NULL;
99db3567 296 unsigned int mode;
b283ef8f 297 char key_name[MAP_KEYNAME_MAXLEN];
99db3567 298
b283ef8f
FDN
299 snprintf(key_name, MAP_KEYNAME_MAXLEN, "%s.%s", path, key);
300 if (map_get_string(key_name, &value) == CS_OK) {
99db3567
JF
301 if (deprecated) {
302 log_printf(LOGSYS_LEVEL_WARNING,
028c4738 303 "Warning: the %s config parameter has been obsoleted."
99db3567 304 " See corosync.conf man page %s directive.",
8a45e2b1 305 key, replacement);
99db3567
JF
306 }
307
c9baa674
JF
308 mode = logsys_config_mode_get (subsys);
309
a1bf354e 310 if (strcmp (value, "yes") == 0 || strcmp (value, "on") == 0) {
99db3567
JF
311 mode |= mode_mask;
312 if (logsys_config_mode_set(subsys, mode) < 0) {
8a45e2b1
JF
313 sprintf (formatted_error_reason, "unable to set mode %s", key);
314 goto parse_error;
99db3567
JF
315 }
316 } else
a1bf354e 317 if (strcmp (value, "no") == 0 || strcmp (value, "off") == 0) {
99db3567
JF
318 mode &= ~mode_mask;
319 if (logsys_config_mode_set(subsys, mode) < 0) {
8a45e2b1
JF
320 sprintf (formatted_error_reason, "unable to unset mode %s", key);
321 goto parse_error;
99db3567
JF
322 }
323 } else {
8a45e2b1
JF
324 sprintf (formatted_error_reason, "unknown value for %s", key);
325 goto parse_error;
99db3567
JF
326 }
327 }
f2a1fcc5
CC
328 /* Set to default if we are the top-level logger */
329 else if (!subsys && !deprecated) {
330
125848d8
CC
331 mode = logsys_config_mode_get (subsys);
332 if (default_value) {
333 mode |= mode_mask;
334 }
335 else {
336 mode &= ~mode_mask;
337 }
338 if (logsys_config_mode_set(subsys, mode) < 0) {
f2a1fcc5 339 sprintf (formatted_error_reason, "unable to change mode %s", key);
125848d8
CC
340 goto parse_error;
341 }
342 }
99db3567 343
8a45e2b1
JF
344 free(value);
345 return (0);
346
347parse_error:
348 *error_string = formatted_error_reason;
349 free(value);
350 return (-1);
99db3567
JF
351}
352
c3c75acf 353static int corosync_main_config_set (
8a45e2b1 354 const char *path,
c3c75acf
FDN
355 const char *subsys,
356 const char **error_string)
357{
358 const char *error_reason = error_string_response;
5ff37d49 359 char *value = NULL;
6d79a218 360 int mode;
b283ef8f 361 char key_name[MAP_KEYNAME_MAXLEN];
c3c75acf
FDN
362
363 /*
364 * this bit abuses the internal logsys exported API
365 * to guarantee that all configured subsystems are
366 * initialized too.
367 *
368 * using this approach avoids some headaches caused
369 * by IPC and TOTEM that have a special logging
370 * handling requirements
371 */
372 if (subsys != NULL) {
37e17e7a 373 if (_logsys_subsys_create(subsys, NULL) < 0) {
c3c75acf
FDN
374 error_reason = "unable to create new logging subsystem";
375 goto parse_error;
376 }
377 }
378
379 mode = logsys_config_mode_get(subsys);
380 if (mode < 0) {
381 error_reason = "unable to get mode";
382 goto parse_error;
383 }
384
8a45e2b1 385 if (corosync_main_config_log_destination_set (path, "to_stderr", subsys, &error_reason,
125848d8 386 LOGSYS_MODE_OUTPUT_STDERR, 0, 1, NULL) != 0)
99db3567 387 goto parse_error;
c3c75acf 388
8a45e2b1 389 if (corosync_main_config_log_destination_set (path, "to_syslog", subsys, &error_reason,
125848d8 390 LOGSYS_MODE_OUTPUT_SYSLOG, 0, 1, NULL) != 0)
99db3567 391 goto parse_error;
c3c75acf 392
b283ef8f
FDN
393 snprintf(key_name, MAP_KEYNAME_MAXLEN, "%s.%s", path, "syslog_facility");
394 if (map_get_string(key_name, &value) == CS_OK) {
c3c75acf
FDN
395 int syslog_facility;
396
78a5260c 397 syslog_facility = qb_log_facility2int(value);
c3c75acf
FDN
398 if (syslog_facility < 0) {
399 error_reason = "unknown syslog facility specified";
400 goto parse_error;
401 }
402 if (logsys_config_syslog_facility_set(subsys,
403 syslog_facility) < 0) {
404 error_reason = "unable to set syslog facility";
405 goto parse_error;
406 }
8a45e2b1
JF
407
408 free(value);
c3c75acf 409 }
125848d8
CC
410 else {
411 /* Set default here in case of a reload */
412 if (logsys_config_syslog_facility_set(subsys,
413 qb_log_facility2int("daemon")) < 0) {
414 error_reason = "unable to set syslog facility";
415 goto parse_error;
416 }
417 }
c3c75acf 418
b283ef8f
FDN
419 snprintf(key_name, MAP_KEYNAME_MAXLEN, "%s.%s", path, "syslog_level");
420 if (map_get_string(key_name, &value) == CS_OK) {
c07b3bdc
FDN
421 int syslog_priority;
422
423 log_printf(LOGSYS_LEVEL_WARNING,
028c4738 424 "Warning: the syslog_level config parameter has been obsoleted."
c07b3bdc
FDN
425 " See corosync.conf man page syslog_priority directive.");
426
427 syslog_priority = logsys_priority_id_get(value);
df6b87f2
JF
428 free(value);
429
c07b3bdc
FDN
430 if (syslog_priority < 0) {
431 error_reason = "unknown syslog level specified";
432 goto parse_error;
433 }
434 if (logsys_config_syslog_priority_set(subsys,
435 syslog_priority) < 0) {
436 error_reason = "unable to set syslog level";
437 goto parse_error;
438 }
439 }
440
b283ef8f
FDN
441 snprintf(key_name, MAP_KEYNAME_MAXLEN, "%s.%s", path, "syslog_priority");
442 if (map_get_string(key_name, &value) == CS_OK) {
c3c75acf
FDN
443 int syslog_priority;
444
445 syslog_priority = logsys_priority_id_get(value);
df6b87f2 446 free(value);
c3c75acf
FDN
447 if (syslog_priority < 0) {
448 error_reason = "unknown syslog priority specified";
449 goto parse_error;
450 }
451 if (logsys_config_syslog_priority_set(subsys,
452 syslog_priority) < 0) {
453 error_reason = "unable to set syslog priority";
454 goto parse_error;
455 }
456 }
d2a5e144 457 else if(strcmp(key_name, "logging.syslog_priority") == 0){
125848d8
CC
458 if (logsys_config_syslog_priority_set(subsys,
459 logsys_priority_id_get("info")) < 0) {
460 error_reason = "unable to set syslog level";
461 goto parse_error;
462 }
463 }
c3c75acf 464
f008cf44 465#ifdef LOGCONFIG_USE_ICMAP
b283ef8f
FDN
466 snprintf(key_name, MAP_KEYNAME_MAXLEN, "%s.%s", path, "logfile");
467 if (map_get_string(key_name, &value) == CS_OK) {
a80febda 468 if (logsys_config_file_set (subsys, &error_reason, value) < 0) {
c3c75acf
FDN
469 goto parse_error;
470 }
8a45e2b1 471 free(value);
c3c75acf 472 }
b283ef8f
FDN
473#else
474 if (!subsys) {
475 if (logsys_config_file_set (subsys, &error_reason, main_logfile) < 0) {
476 goto parse_error;
477 }
478 }
479#endif
c3c75acf 480
8a45e2b1 481 if (corosync_main_config_log_destination_set (path, "to_file", subsys, &error_reason,
125848d8 482 LOGSYS_MODE_OUTPUT_FILE, 1, 0, "to_logfile") != 0)
8a45e2b1
JF
483 goto parse_error;
484
485 if (corosync_main_config_log_destination_set (path, "to_logfile", subsys, &error_reason,
125848d8 486 LOGSYS_MODE_OUTPUT_FILE, 0, 0, NULL) != 0)
0e58141a
AS
487 goto parse_error;
488
b283ef8f
FDN
489 snprintf(key_name, MAP_KEYNAME_MAXLEN, "%s.%s", path, "logfile_priority");
490 if (map_get_string(key_name, &value) == CS_OK) {
c3c75acf
FDN
491 int logfile_priority;
492
493 logfile_priority = logsys_priority_id_get(value);
df6b87f2 494 free(value);
c3c75acf
FDN
495 if (logfile_priority < 0) {
496 error_reason = "unknown logfile priority specified";
497 goto parse_error;
498 }
499 if (logsys_config_logfile_priority_set(subsys,
500 logfile_priority) < 0) {
501 error_reason = "unable to set logfile priority";
a549daed
JM
502 goto parse_error;
503 }
c3c75acf 504 }
d2a5e144 505 else if(strcmp(key_name,"logging.logfile_priority") == 0){
125848d8
CC
506 if (logsys_config_logfile_priority_set(subsys,
507 logsys_priority_id_get("info")) < 0) {
508 error_reason = "unable to set syslog level";
509 goto parse_error;
510 }
511 }
dbca1c61 512
b283ef8f
FDN
513 snprintf(key_name, MAP_KEYNAME_MAXLEN, "%s.%s", path, "debug");
514 if (map_get_string(key_name, &value) == CS_OK) {
57176550
JF
515 if (strcmp (value, "trace") == 0) {
516 if (logsys_config_debug_set (subsys, LOGSYS_DEBUG_TRACE) < 0) {
517 error_reason = "unable to set debug trace";
df6b87f2 518 free(value);
57176550
JF
519 goto parse_error;
520 }
521 } else
c3c75acf 522 if (strcmp (value, "on") == 0) {
57176550 523 if (logsys_config_debug_set (subsys, LOGSYS_DEBUG_ON) < 0) {
c3c75acf 524 error_reason = "unable to set debug on";
df6b87f2 525 free(value);
c3c75acf
FDN
526 goto parse_error;
527 }
528 } else
529 if (strcmp (value, "off") == 0) {
57176550 530 if (logsys_config_debug_set (subsys, LOGSYS_DEBUG_OFF) < 0) {
c3c75acf 531 error_reason = "unable to set debug off";
df6b87f2 532 free(value);
c3c75acf
FDN
533 goto parse_error;
534 }
535 } else {
536 error_reason = "unknown value for debug";
df6b87f2 537 free(value);
c3c75acf 538 goto parse_error;
dbca1c61 539 }
8a45e2b1 540 free(value);
c3c75acf 541 }
125848d8
CC
542 else {
543 if (logsys_config_debug_set (subsys, LOGSYS_DEBUG_OFF) < 0) {
544 error_reason = "unable to set debug off";
125848d8
CC
545 goto parse_error;
546 }
547 }
c3c75acf 548
c3c75acf
FDN
549 return (0);
550
551parse_error:
552 *error_string = error_reason;
553
554 return (-1);
555}
556
557static int corosync_main_config_read_logging (
c3c75acf
FDN
558 const char **error_string)
559{
c3c75acf 560 const char *error_reason;
f008cf44 561#ifdef LOGCONFIG_USE_ICMAP
8a45e2b1
JF
562 icmap_iter_t iter;
563 const char *key_name;
b283ef8f
FDN
564#else
565 cmap_iter_handle_t iter;
566 char key_name[CMAP_KEYNAME_MAXLEN];
567#endif
568 char key_subsys[MAP_KEYNAME_MAXLEN];
569 char key_item[MAP_KEYNAME_MAXLEN];
8a45e2b1 570 int res;
c3c75acf 571
8a45e2b1
JF
572 /* format set is supported only for toplevel */
573 if (corosync_main_config_format_set(&error_reason) < 0) {
574 goto parse_error;
575 }
c3c75acf 576
79dba9c5
JF
577 if (corosync_main_config_blackbox_set(&error_reason) < 0) {
578 goto parse_error;
579 }
580
8a45e2b1
JF
581 if (corosync_main_config_set ("logging", NULL, &error_reason) < 0) {
582 goto parse_error;
583 }
c3c75acf 584
8a45e2b1
JF
585 /*
586 * we will need 2 of these to compensate for new logging
587 * config format
588 */
f008cf44 589#ifdef LOGCONFIG_USE_ICMAP
8a45e2b1
JF
590 iter = icmap_iter_init("logging.logger_subsys.");
591 while ((key_name = icmap_iter_next(iter, NULL, NULL)) != NULL) {
b283ef8f
FDN
592#else
593 cmap_iter_init(cmap_handle, "logging.logger_subsys.", &iter);
594 while ((cmap_iter_next(cmap_handle, iter, key_name, NULL, NULL)) == CS_OK) {
595#endif
8a45e2b1 596 res = sscanf(key_name, "logging.logger_subsys.%[^.].%s", key_subsys, key_item);
c3c75acf 597
8a45e2b1
JF
598 if (res != 2) {
599 continue ;
c3c75acf
FDN
600 }
601
8a45e2b1
JF
602 if (strcmp(key_item, "subsys") != 0) {
603 continue ;
c3c75acf 604 }
8a45e2b1 605
cc81696f
JF
606 if (snprintf(key_item, MAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s",
607 key_subsys) >= MAP_KEYNAME_MAXLEN) {
608 /*
609 * This should never happen
610 */
611 error_reason = "Can't snprintf logger_subsys key_item";
612 goto parse_error;
613 }
8a45e2b1
JF
614
615 if (corosync_main_config_set(key_item, key_subsys, &error_reason) < 0) {
616 goto parse_error;
f50a6a11 617 }
3568f266 618 }
f008cf44 619#ifdef LOGCONFIG_USE_ICMAP
8a45e2b1 620 icmap_iter_finalize(iter);
b283ef8f
FDN
621#else
622 cmap_iter_finalize(cmap_handle, iter);
623#endif
5c257afb 624
37e17e7a 625 logsys_config_apply();
f5467e33
CC
626 return 0;
627
628parse_error:
c3c75acf 629 *error_string = error_reason;
f5467e33 630
f5467e33
CC
631 return (-1);
632}
633
f008cf44 634#ifdef LOGCONFIG_USE_ICMAP
8a45e2b1
JF
635static void main_logging_notify(
636 int32_t event,
637 const char *key_name,
638 struct icmap_notify_value new_val,
639 struct icmap_notify_value old_val,
640 void *user_data)
b283ef8f
FDN
641#else
642static void main_logging_notify(
643 cmap_handle_t cmap_handle_unused,
644 cmap_handle_t cmap_track_handle_unused,
645 int32_t event,
646 const char *key_name,
647 struct cmap_notify_value new_val,
648 struct cmap_notify_value old_val,
649 void *user_data)
650#endif
c3c75acf
FDN
651{
652 const char *error_string;
1a046793
CC
653 static int reload_in_progress = 0;
654
655 /* If a full reload happens then suspend updates for individual keys until
656 * it's all completed
657 */
658 if (strcmp(key_name, "config.reload_in_progress") == 0) {
659 if (*(uint8_t *)new_val.data == 1) {
660 reload_in_progress = 1;
661 } else {
662 reload_in_progress = 0;
663 }
664 }
665 if (reload_in_progress) {
666 log_printf(LOGSYS_LEVEL_DEBUG, "Ignoring key change, reload in progress. %s\n", key_name);
667 return;
668 }
c3c75acf 669
8a45e2b1
JF
670 /*
671 * Reload the logsys configuration
672 */
673 if (logsys_format_set(NULL) == -1) {
674 fprintf (stderr, "Unable to setup logging format.\n");
c3c75acf 675 }
8a45e2b1 676 corosync_main_config_read_logging(&error_string);
c3c75acf
FDN
677}
678
f008cf44 679#ifdef LOGCONFIG_USE_ICMAP
8a45e2b1 680static void add_logsys_config_notification(void)
c3c75acf 681{
2967ad3b 682 icmap_track_t icmap_track = NULL;
c3c75acf 683
8a45e2b1
JF
684 icmap_track_add("logging.",
685 ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY | ICMAP_TRACK_PREFIX,
686 main_logging_notify,
687 NULL,
688 &icmap_track);
1a046793
CC
689
690 icmap_track_add("config.reload_in_progress",
691 ICMAP_TRACK_ADD | ICMAP_TRACK_MODIFY,
692 main_logging_notify,
693 NULL,
694 &icmap_track);
ae229831 695}
b283ef8f
FDN
696#else
697static void add_logsys_config_notification(void)
698{
699 cmap_track_handle_t cmap_track;
700
701 cmap_track_add(cmap_handle, "logging.",
702 CMAP_TRACK_ADD | CMAP_TRACK_DELETE | CMAP_TRACK_MODIFY | CMAP_TRACK_PREFIX,
703 main_logging_notify,
704 NULL,
705 &cmap_track);
1a046793
CC
706
707 cmap_track_add(cmap_handle, "config.reload_in_progress",
708 CMAP_TRACK_ADD | CMAP_TRACK_MODIFY,
709 main_logging_notify,
710 NULL,
711 &cmap_track);
b283ef8f
FDN
712}
713#endif
ae229831 714
f008cf44
FDN
715int corosync_log_config_read (
716#ifndef LOGCONFIG_USE_ICMAP
b283ef8f
FDN
717 cmap_handle_t cmap_h,
718 const char *default_logfile,
719#endif
bc87f196 720 const char **error_string)
f5467e33 721{
9e2fa013 722 const char *error_reason = error_string_response;
f5467e33 723
f008cf44 724#ifndef LOGCONFIG_USE_ICMAP
b283ef8f
FDN
725 if (!cmap_h) {
726 error_reason = "No cmap handle";
727 return (-1);
728 }
729 if (!default_logfile) {
730 error_reason = "No default logfile";
731 return (-1);
732 }
733 cmap_handle = cmap_h;
734 main_logfile = default_logfile;
735#endif
736
8a45e2b1 737 if (corosync_main_config_read_logging(error_string) < 0) {
c3c75acf
FDN
738 error_reason = *error_string;
739 goto parse_error;
740 }
f5467e33 741
8a45e2b1 742 add_logsys_config_notification();
f5467e33 743
3568f266 744 return 0;
7b2ddfa4
SD
745
746parse_error:
870046d0 747 snprintf (error_string_response, sizeof(error_string_response),
3568f266
PC
748 "parse error in config: %s.\n",
749 error_reason);
750
7b2ddfa4 751 *error_string = error_string_response;
7b2ddfa4
SD
752 return (-1);
753}