This source file includes following definitions.
- crm_glib_handler
- crm_trigger_blackbox
- daemon_option
- set_daemon_option
- daemon_option_enabled
- crm_log_deinit
- set_format_string
- crm_add_logfile
- blackbox_logger
- crm_control_blackbox
- crm_enable_blackbox
- crm_disable_blackbox
- crm_write_blackbox
- crm_log_cli_init
- crm_quark_to_string
- crm_log_filter_source
- crm_log_filter
- crm_is_callsite_active
- crm_update_callsites
- crm_tracing_enabled
- crm_priority2int
- crm_identity
- crm_log_preinit
- crm_log_init
- set_crm_log_level
- crm_enable_stderr
- crm_bump_log_level
- get_crm_log_level
- crm_log_args
- pcmk_errorname
- pcmk_strerror
- bz2_strerror
- crm_log_output_fn
- crm_strdup_printf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <crm_internal.h>
20
21 #include <sys/param.h>
22 #include <sys/types.h>
23 #include <sys/wait.h>
24 #include <sys/stat.h>
25 #include <sys/utsname.h>
26
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <limits.h>
32 #include <ctype.h>
33 #include <pwd.h>
34 #include <grp.h>
35 #include <time.h>
36 #include <libgen.h>
37 #include <signal.h>
38 #include <bzlib.h>
39
40 #include <qb/qbdefs.h>
41
42 #include <crm/crm.h>
43 #include <crm/common/mainloop.h>
44
45 unsigned int crm_log_priority = LOG_NOTICE;
46 unsigned int crm_log_level = LOG_INFO;
47 static gboolean crm_tracing_enabled(void);
48 unsigned int crm_trace_nonlog = 0;
49 bool crm_is_daemon = 0;
50
51 #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER
52 GLogFunc glib_log_default;
53
54 static void
55 crm_glib_handler(const gchar * log_domain, GLogLevelFlags flags, const gchar * message,
56 gpointer user_data)
57 {
58 int log_level = LOG_WARNING;
59 GLogLevelFlags msg_level = (flags & G_LOG_LEVEL_MASK);
60 static struct qb_log_callsite *glib_cs = NULL;
61
62 if (glib_cs == NULL) {
63 glib_cs = qb_log_callsite_get(__FUNCTION__, __FILE__, "glib-handler", LOG_DEBUG, __LINE__, crm_trace_nonlog);
64 }
65
66
67 switch (msg_level) {
68 case G_LOG_LEVEL_CRITICAL:
69 log_level = LOG_CRIT;
70
71 if (crm_is_callsite_active(glib_cs, LOG_DEBUG, 0) == FALSE) {
72
73 crm_abort(__FILE__, __FUNCTION__, __LINE__, message, TRUE, TRUE);
74 }
75 break;
76
77 case G_LOG_LEVEL_ERROR:
78 log_level = LOG_ERR;
79 break;
80 case G_LOG_LEVEL_MESSAGE:
81 log_level = LOG_NOTICE;
82 break;
83 case G_LOG_LEVEL_INFO:
84 log_level = LOG_INFO;
85 break;
86 case G_LOG_LEVEL_DEBUG:
87 log_level = LOG_DEBUG;
88 break;
89
90 case G_LOG_LEVEL_WARNING:
91 case G_LOG_FLAG_RECURSION:
92 case G_LOG_FLAG_FATAL:
93 case G_LOG_LEVEL_MASK:
94 log_level = LOG_WARNING;
95 break;
96 }
97
98 do_crm_log(log_level, "%s: %s", log_domain, message);
99 }
100 #endif
101
102 #ifndef NAME_MAX
103 # define NAME_MAX 256
104 #endif
105
106 static void
107 crm_trigger_blackbox(int nsig)
108 {
109 if(nsig == SIGTRAP) {
110
111 crm_enable_blackbox(nsig);
112 }
113 crm_write_blackbox(nsig, NULL);
114 }
115
116 const char *
117 daemon_option(const char *option)
118 {
119 char env_name[NAME_MAX];
120 const char *value = NULL;
121
122 snprintf(env_name, NAME_MAX, "PCMK_%s", option);
123 value = getenv(env_name);
124 if (value != NULL) {
125 crm_trace("Found %s = %s", env_name, value);
126 return value;
127 }
128
129 snprintf(env_name, NAME_MAX, "HA_%s", option);
130 value = getenv(env_name);
131 if (value != NULL) {
132 crm_trace("Found %s = %s", env_name, value);
133 return value;
134 }
135
136 crm_trace("Nothing found for %s", option);
137 return NULL;
138 }
139
140 void
141 set_daemon_option(const char *option, const char *value)
142 {
143 char env_name[NAME_MAX];
144
145 snprintf(env_name, NAME_MAX, "PCMK_%s", option);
146 if (value) {
147 crm_trace("Setting %s to %s", env_name, value);
148 setenv(env_name, value, 1);
149 } else {
150 crm_trace("Unsetting %s", env_name);
151 unsetenv(env_name);
152 }
153
154 snprintf(env_name, NAME_MAX, "HA_%s", option);
155 if (value) {
156 crm_trace("Setting %s to %s", env_name, value);
157 setenv(env_name, value, 1);
158 } else {
159 crm_trace("Unsetting %s", env_name);
160 unsetenv(env_name);
161 }
162 }
163
164 gboolean
165 daemon_option_enabled(const char *daemon, const char *option)
166 {
167 const char *value = daemon_option(option);
168
169 if (value != NULL && crm_is_true(value)) {
170 return TRUE;
171
172 } else if (value != NULL && strstr(value, daemon)) {
173 return TRUE;
174 }
175
176 return FALSE;
177 }
178
179 void
180 crm_log_deinit(void)
181 {
182 #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER
183 g_log_set_default_handler(glib_log_default, NULL);
184 #endif
185 }
186
187 #define FMT_MAX 256
188 static void
189 set_format_string(int method, const char *daemon)
190 {
191 int offset = 0;
192 char fmt[FMT_MAX];
193
194 if (method > QB_LOG_STDERR) {
195
196 struct utsname res;
197
198 if (uname(&res) == 0) {
199 offset +=
200 snprintf(fmt + offset, FMT_MAX - offset, "%%t [%lu] %s %10s: ",
201 (unsigned long) getpid(), res.nodename, daemon);
202 } else {
203 offset += snprintf(fmt + offset, FMT_MAX - offset, "%%t [%lu] %10s: ",
204 (unsigned long) getpid(), daemon);
205 }
206 }
207
208 if (method == QB_LOG_SYSLOG) {
209 offset += snprintf(fmt + offset, FMT_MAX - offset, "%%g %%-7p: %%b");
210 crm_extended_logging(method, QB_FALSE);
211 } else if (crm_tracing_enabled()) {
212 offset += snprintf(fmt + offset, FMT_MAX - offset, "(%%-12f:%%5l %%g) %%-7p: %%n:\t%%b");
213 } else {
214 offset += snprintf(fmt + offset, FMT_MAX - offset, "%%g %%-7p: %%n:\t%%b");
215 }
216
217 CRM_LOG_ASSERT(offset > 0);
218 qb_log_format_set(method, fmt);
219 }
220
221 gboolean
222 crm_add_logfile(const char *filename)
223 {
224 bool is_default = false;
225 static int default_fd = -1;
226 static gboolean have_logfile = FALSE;
227
228
229
230
231 const char *default_logfile = "/var/log/pacemaker.log";
232
233 struct stat parent;
234 int fd = 0, rc = 0;
235 FILE *logfile = NULL;
236 char *parent_dir = NULL;
237 char *filename_cp;
238
239 if (filename == NULL && have_logfile == FALSE) {
240 filename = default_logfile;
241 }
242
243 if (filename == NULL) {
244 return FALSE;
245 } else if(safe_str_eq(filename, "none")) {
246 return FALSE;
247 } else if(safe_str_eq(filename, "/dev/null")) {
248 return FALSE;
249 } else if(safe_str_eq(filename, default_logfile)) {
250 is_default = TRUE;
251 }
252
253 if(is_default && default_fd >= 0) {
254 return TRUE;
255 }
256
257
258 filename_cp = strdup(filename);
259 parent_dir = dirname(filename_cp);
260 rc = stat(parent_dir, &parent);
261
262 if (rc != 0) {
263 crm_err("Directory '%s' does not exist: logging to '%s' is disabled", parent_dir, filename);
264 free(filename_cp);
265 return FALSE;
266 }
267 free(filename_cp);
268
269 errno = 0;
270 logfile = fopen(filename, "a");
271 if(logfile == NULL) {
272 crm_err("%s (%d): Logging to '%s' as uid=%u, gid=%u is disabled",
273 pcmk_strerror(errno), errno, filename, geteuid(), getegid());
274 return FALSE;
275 }
276
277
278 if (geteuid() == 0) {
279 struct stat st;
280 uid_t pcmk_uid = 0;
281 gid_t pcmk_gid = 0;
282 gboolean fix = FALSE;
283 int logfd = fileno(logfile);
284
285 rc = fstat(logfd, &st);
286 if (rc < 0) {
287 crm_perror(LOG_WARNING, "Cannot stat %s", filename);
288 fclose(logfile);
289 return FALSE;
290 }
291
292 if(crm_user_lookup(CRM_DAEMON_USER, &pcmk_uid, &pcmk_gid) == 0) {
293 if (st.st_gid != pcmk_gid) {
294
295 fix = TRUE;
296 } else if ((st.st_mode & S_IRWXG) != (S_IRGRP | S_IWGRP)) {
297
298 fix = TRUE;
299 }
300 }
301
302 if (fix) {
303 rc = fchown(logfd, pcmk_uid, pcmk_gid);
304 if (rc < 0) {
305 crm_warn("Cannot change the ownership of %s to user %s and gid %d",
306 filename, CRM_DAEMON_USER, pcmk_gid);
307 }
308
309 rc = fchmod(logfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
310 if (rc < 0) {
311 crm_warn("Cannot change the mode of %s to rw-rw----", filename);
312 }
313
314 fprintf(logfile, "Set r/w permissions for uid=%d, gid=%d on %s\n",
315 pcmk_uid, pcmk_gid, filename);
316 if (fflush(logfile) < 0 || fsync(logfd) < 0) {
317 crm_err("Couldn't write out logfile: %s", filename);
318 }
319 }
320 }
321
322
323 fclose(logfile);
324 fd = qb_log_file_open(filename);
325
326 if (fd < 0) {
327 crm_perror(LOG_WARNING, "Couldn't send additional logging to %s", filename);
328 return FALSE;
329 }
330
331 if(is_default) {
332 default_fd = fd;
333
334 } else if(default_fd >= 0) {
335 crm_notice("Switching to %s", filename);
336 qb_log_ctl(default_fd, QB_LOG_CONF_ENABLED, QB_FALSE);
337 }
338
339 crm_notice("Additional logging available in %s", filename);
340 qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_TRUE);
341
342
343
344 crm_update_callsites();
345 have_logfile = TRUE;
346
347 return TRUE;
348 }
349
350 static int blackbox_trigger = 0;
351 static char *blackbox_file_prefix = NULL;
352
353 static void
354 blackbox_logger(int32_t t, struct qb_log_callsite *cs, time_t timestamp, const char *msg)
355 {
356 if(cs && cs->priority < LOG_ERR) {
357 crm_write_blackbox(SIGTRAP, cs);
358 } else {
359 crm_write_blackbox(0, cs);
360 }
361 }
362
363 static void
364 crm_control_blackbox(int nsig, bool enable)
365 {
366 int lpc = 0;
367
368 if (blackbox_file_prefix == NULL) {
369 pid_t pid = getpid();
370
371 blackbox_file_prefix = malloc(NAME_MAX);
372 snprintf(blackbox_file_prefix, NAME_MAX, "%s/%s-%lu",
373 CRM_BLACKBOX_DIR, crm_system_name, (unsigned long) pid);
374 }
375
376 if (enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
377 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 5 * 1024 * 1024);
378 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
379
380
381 for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
382 qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_TRUE);
383 }
384
385 crm_notice("Initiated blackbox recorder: %s", blackbox_file_prefix);
386
387
388 crm_signal(SIGSEGV, crm_trigger_blackbox);
389 crm_signal(SIGABRT, crm_trigger_blackbox);
390 crm_signal(SIGILL, crm_trigger_blackbox);
391 crm_signal(SIGBUS, crm_trigger_blackbox);
392 crm_signal(SIGFPE, crm_trigger_blackbox);
393
394 crm_update_callsites();
395
396 blackbox_trigger = qb_log_custom_open(blackbox_logger, NULL, NULL, NULL);
397 qb_log_ctl(blackbox_trigger, QB_LOG_CONF_ENABLED, QB_TRUE);
398 crm_trace("Trigger: %d is %d %d", blackbox_trigger,
399 qb_log_ctl(blackbox_trigger, QB_LOG_CONF_STATE_GET, 0), QB_LOG_STATE_ENABLED);
400
401 crm_update_callsites();
402
403 } else if (!enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
404 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
405
406
407 for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
408 qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_FALSE);
409 }
410 }
411 }
412
413 void
414 crm_enable_blackbox(int nsig)
415 {
416 crm_control_blackbox(nsig, TRUE);
417 }
418
419 void
420 crm_disable_blackbox(int nsig)
421 {
422 crm_control_blackbox(nsig, FALSE);
423 }
424
425 void
426 crm_write_blackbox(int nsig, struct qb_log_callsite *cs)
427 {
428 static int counter = 1;
429 static time_t last = 0;
430
431 char buffer[NAME_MAX];
432 time_t now = time(NULL);
433
434 if (blackbox_file_prefix == NULL) {
435 return;
436 }
437
438 switch (nsig) {
439 case 0:
440 case SIGTRAP:
441
442
443 if (nsig == 0 && now == last) {
444
445 return;
446 }
447
448 snprintf(buffer, NAME_MAX, "%s.%d", blackbox_file_prefix, counter++);
449 if (nsig == SIGTRAP) {
450 crm_notice("Blackbox dump requested, please see %s for contents", buffer);
451
452 } else if (cs) {
453 syslog(LOG_NOTICE,
454 "Problem detected at %s:%d (%s), please see %s for additional details",
455 cs->function, cs->lineno, cs->filename, buffer);
456 } else {
457 crm_notice("Problem detected, please see %s for additional details", buffer);
458 }
459
460 last = now;
461 qb_log_blackbox_write_to_file(buffer);
462
463
464
465
466 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
467 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
468 break;
469
470 default:
471
472
473
474 crm_signal(nsig, SIG_DFL);
475 qb_log_blackbox_write_to_file(blackbox_file_prefix);
476 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
477 raise(nsig);
478 break;
479 }
480 }
481
482 gboolean
483 crm_log_cli_init(const char *entity)
484 {
485 return crm_log_init(entity, LOG_ERR, FALSE, FALSE, 0, NULL, TRUE);
486 }
487
488 static const char *
489 crm_quark_to_string(uint32_t tag)
490 {
491 const char *text = g_quark_to_string(tag);
492
493 if (text) {
494 return text;
495 }
496 return "";
497 }
498
499 static void
500 crm_log_filter_source(int source, const char *trace_files, const char *trace_fns,
501 const char *trace_fmts, const char *trace_tags, const char *trace_blackbox,
502 struct qb_log_callsite *cs)
503 {
504 if (qb_log_ctl(source, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
505 return;
506 } else if (cs->tags != crm_trace_nonlog && source == QB_LOG_BLACKBOX) {
507
508 qb_bit_set(cs->targets, source);
509
510 } else if (source == blackbox_trigger && blackbox_trigger > 0) {
511
512 if (cs->priority <= LOG_ERR) {
513 qb_bit_set(cs->targets, source);
514
515 } else if (trace_blackbox) {
516 char *key = crm_strdup_printf("%s:%d", cs->function, cs->lineno);
517
518 if (strstr(trace_blackbox, key) != NULL) {
519 qb_bit_set(cs->targets, source);
520 }
521 free(key);
522 }
523
524 } else if (source == QB_LOG_SYSLOG) {
525 if (cs->priority <= crm_log_priority && cs->priority <= crm_log_level) {
526 qb_bit_set(cs->targets, source);
527 }
528
529 } else if (cs->priority <= crm_log_level) {
530 qb_bit_set(cs->targets, source);
531 } else if (trace_files && strstr(trace_files, cs->filename) != NULL) {
532 qb_bit_set(cs->targets, source);
533 } else if (trace_fns && strstr(trace_fns, cs->function) != NULL) {
534 qb_bit_set(cs->targets, source);
535 } else if (trace_fmts && strstr(trace_fmts, cs->format) != NULL) {
536 qb_bit_set(cs->targets, source);
537 } else if (trace_tags
538 && cs->tags != 0
539 && cs->tags != crm_trace_nonlog && g_quark_to_string(cs->tags) != NULL) {
540 qb_bit_set(cs->targets, source);
541 }
542 }
543
544 static void
545 crm_log_filter(struct qb_log_callsite *cs)
546 {
547 int lpc = 0;
548 static int need_init = 1;
549 static const char *trace_fns = NULL;
550 static const char *trace_tags = NULL;
551 static const char *trace_fmts = NULL;
552 static const char *trace_files = NULL;
553 static const char *trace_blackbox = NULL;
554
555 if (need_init) {
556 need_init = 0;
557 trace_fns = getenv("PCMK_trace_functions");
558 trace_fmts = getenv("PCMK_trace_formats");
559 trace_tags = getenv("PCMK_trace_tags");
560 trace_files = getenv("PCMK_trace_files");
561 trace_blackbox = getenv("PCMK_trace_blackbox");
562
563 if (trace_tags != NULL) {
564 uint32_t tag;
565 char token[500];
566 const char *offset = NULL;
567 const char *next = trace_tags;
568
569 do {
570 offset = next;
571 next = strchrnul(offset, ',');
572 snprintf(token, sizeof(token), "%.*s", (int)(next - offset), offset);
573
574 tag = g_quark_from_string(token);
575 crm_info("Created GQuark %u from token '%s' in '%s'", tag, token, trace_tags);
576
577 if (next[0] != 0) {
578 next++;
579 }
580
581 } while (next != NULL && next[0] != 0);
582 }
583 }
584
585 cs->targets = 0;
586 for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
587 crm_log_filter_source(lpc, trace_files, trace_fns, trace_fmts, trace_tags, trace_blackbox,
588 cs);
589 }
590 }
591
592 gboolean
593 crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
594 {
595 gboolean refilter = FALSE;
596
597 if (cs == NULL) {
598 return FALSE;
599 }
600
601 if (cs->priority != level) {
602 cs->priority = level;
603 refilter = TRUE;
604 }
605
606 if (cs->tags != tags) {
607 cs->tags = tags;
608 refilter = TRUE;
609 }
610
611 if (refilter) {
612 crm_log_filter(cs);
613 }
614
615 if (cs->targets == 0) {
616 return FALSE;
617 }
618 return TRUE;
619 }
620
621 void
622 crm_update_callsites(void)
623 {
624 static gboolean log = TRUE;
625
626 if (log) {
627 log = FALSE;
628 crm_debug
629 ("Enabling callsites based on priority=%d, files=%s, functions=%s, formats=%s, tags=%s",
630 crm_log_level, getenv("PCMK_trace_files"), getenv("PCMK_trace_functions"),
631 getenv("PCMK_trace_formats"), getenv("PCMK_trace_tags"));
632 }
633 qb_log_filter_fn_set(crm_log_filter);
634 }
635
636 static gboolean
637 crm_tracing_enabled(void)
638 {
639 if (crm_log_level >= LOG_TRACE) {
640 return TRUE;
641 } else if (getenv("PCMK_trace_files") || getenv("PCMK_trace_functions")
642 || getenv("PCMK_trace_formats") || getenv("PCMK_trace_tags")) {
643 return TRUE;
644 }
645 return FALSE;
646 }
647
648 static int
649 crm_priority2int(const char *name)
650 {
651 struct syslog_names {
652 const char *name;
653 int priority;
654 };
655 static struct syslog_names p_names[] = {
656 {"emerg", LOG_EMERG},
657 {"alert", LOG_ALERT},
658 {"crit", LOG_CRIT},
659 {"error", LOG_ERR},
660 {"warning", LOG_WARNING},
661 {"notice", LOG_NOTICE},
662 {"info", LOG_INFO},
663 {"debug", LOG_DEBUG},
664 {NULL, -1}
665 };
666 int lpc;
667
668 for (lpc = 0; name != NULL && p_names[lpc].name != NULL; lpc++) {
669 if (crm_str_eq(p_names[lpc].name, name, TRUE)) {
670 return p_names[lpc].priority;
671 }
672 }
673 return crm_log_priority;
674 }
675
676
677 static void
678 crm_identity(const char *entity, int argc, char **argv)
679 {
680 if(crm_system_name != NULL) {
681
682
683 } else if (entity) {
684 free(crm_system_name);
685 crm_system_name = strdup(entity);
686
687 } else if (argc > 0 && argv != NULL) {
688 char *mutable = strdup(argv[0]);
689 char *modified = basename(mutable);
690
691 if (strstr(modified, "lt-") == modified) {
692 modified += 3;
693 }
694
695 free(crm_system_name);
696 crm_system_name = strdup(modified);
697 free(mutable);
698
699 } else if (crm_system_name == NULL) {
700 crm_system_name = strdup("Unknown");
701 }
702
703 setenv("PCMK_service", crm_system_name, 1);
704 }
705
706
707 void
708 crm_log_preinit(const char *entity, int argc, char **argv)
709 {
710
711
712 int lpc = 0;
713 int32_t qb_facility = 0;
714
715 static bool have_logging = FALSE;
716
717 if(have_logging == FALSE) {
718 have_logging = TRUE;
719
720 crm_xml_init();
721
722 if (crm_trace_nonlog == 0) {
723 crm_trace_nonlog = g_quark_from_static_string("Pacemaker non-logging tracepoint");
724 }
725
726 umask(S_IWGRP | S_IWOTH | S_IROTH);
727
728
729 #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER
730 glib_log_default = g_log_set_default_handler(crm_glib_handler, NULL);
731 #endif
732
733
734 g_log_set_always_fatal((GLogLevelFlags) 0);
735
736
737 crm_identity(entity, argc, argv);
738
739 qb_facility = qb_log_facility2int("local0");
740 qb_log_init(crm_system_name, qb_facility, LOG_ERR);
741 crm_log_level = LOG_CRIT;
742
743
744 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
745
746
747
748
749 qb_log_tags_stringify_fn_set(crm_quark_to_string);
750 for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
751 qb_log_ctl(lpc, QB_LOG_CONF_THREADED, QB_FALSE);
752 set_format_string(lpc, crm_system_name);
753 }
754 }
755 }
756
757 gboolean
758 crm_log_init(const char *entity, uint8_t level, gboolean daemon, gboolean to_stderr,
759 int argc, char **argv, gboolean quiet)
760 {
761 const char *syslog_priority = NULL;
762 const char *logfile = daemon_option("logfile");
763 const char *facility = daemon_option("logfacility");
764 const char *f_copy = facility;
765
766 crm_is_daemon = daemon;
767 crm_log_preinit(entity, argc, argv);
768
769 if(level > crm_log_level) {
770 crm_log_level = level;
771 }
772
773
774 if (facility == NULL) {
775 if(crm_is_daemon) {
776 facility = "daemon";
777 } else {
778 facility = "none";
779 }
780 set_daemon_option("logfacility", facility);
781 }
782
783 if (safe_str_eq(facility, "none")) {
784 quiet = TRUE;
785
786
787 } else {
788 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, qb_log_facility2int(facility));
789 }
790
791 if (daemon_option_enabled(crm_system_name, "debug")) {
792
793 crm_log_level = LOG_DEBUG;
794 }
795
796
797 syslog_priority = daemon_option("logpriority");
798 if(syslog_priority) {
799 int priority = crm_priority2int(syslog_priority);
800 crm_log_priority = priority;
801 qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE, "*", priority);
802 } else {
803 qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE, "*", LOG_NOTICE);
804 }
805
806 if (!quiet) {
807
808 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
809 }
810
811
812 if (daemon_option_enabled(crm_system_name, "stderr")) {
813
814 to_stderr = TRUE;
815 }
816 crm_enable_stderr(to_stderr);
817
818
819 if (safe_str_eq("none", logfile)) {
820
821 } else if(crm_is_daemon) {
822
823 crm_add_logfile(logfile);
824 } else if(logfile) {
825 crm_add_logfile(logfile);
826 }
827
828 if (crm_is_daemon && daemon_option_enabled(crm_system_name, "blackbox")) {
829 crm_enable_blackbox(0);
830 }
831
832
833 crm_trace("Quiet: %d, facility %s", quiet, f_copy);
834 daemon_option("logfile");
835 daemon_option("logfacility");
836
837 crm_update_callsites();
838
839
840 if (quiet == FALSE && crm_is_daemon == FALSE) {
841 crm_log_args(argc, argv);
842 }
843
844 if (crm_is_daemon) {
845 const char *user = getenv("USER");
846
847 if (user != NULL && safe_str_neq(user, "root") && safe_str_neq(user, CRM_DAEMON_USER)) {
848 crm_trace("Not switching to corefile directory for %s", user);
849 crm_is_daemon = FALSE;
850 }
851 }
852
853 if (crm_is_daemon) {
854 int user = getuid();
855 const char *base = CRM_CORE_DIR;
856 struct passwd *pwent = getpwuid(user);
857
858 if (pwent == NULL) {
859 crm_perror(LOG_ERR, "Cannot get name for uid: %d", user);
860
861 } else if (safe_str_neq(pwent->pw_name, "root")
862 && safe_str_neq(pwent->pw_name, CRM_DAEMON_USER)) {
863 crm_trace("Don't change active directory for regular user: %s", pwent->pw_name);
864
865 } else if (chdir(base) < 0) {
866 crm_perror(LOG_INFO, "Cannot change active directory to %s", base);
867
868 } else {
869 crm_info("Changed active directory to %s", base);
870 #if 0
871 {
872 char path[512];
873
874 snprintf(path, 512, "%s-%lu", crm_system_name, (unsigned long) getpid());
875 mkdir(path, 0750);
876 chdir(path);
877 crm_info("Changed active directory to %s/%s/%s", base, pwent->pw_name, path);
878 }
879 #endif
880 }
881
882
883
884
885
886
887
888
889
890
891 mainloop_add_signal(SIGUSR1, crm_enable_blackbox);
892 mainloop_add_signal(SIGUSR2, crm_disable_blackbox);
893 mainloop_add_signal(SIGTRAP, crm_trigger_blackbox);
894 }
895
896 return TRUE;
897 }
898
899
900 unsigned int
901 set_crm_log_level(unsigned int level)
902 {
903 unsigned int old = crm_log_level;
904
905 crm_log_level = level;
906 crm_update_callsites();
907 crm_trace("New log level: %d", level);
908 return old;
909 }
910
911 void
912 crm_enable_stderr(int enable)
913 {
914 if (enable && qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
915 qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
916 crm_update_callsites();
917
918 } else if (enable == FALSE) {
919 qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE);
920 }
921 }
922
923 void
924 crm_bump_log_level(int argc, char **argv)
925 {
926 static int args = TRUE;
927 int level = crm_log_level;
928
929 if (args && argc > 1) {
930 crm_log_args(argc, argv);
931 }
932
933 if (qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
934 set_crm_log_level(level + 1);
935 }
936
937
938 crm_enable_stderr(TRUE);
939 }
940
941 unsigned int
942 get_crm_log_level(void)
943 {
944 return crm_log_level;
945 }
946
947 #define ARGS_FMT "Invoked: %s"
948 void
949 crm_log_args(int argc, char **argv)
950 {
951 int lpc = 0;
952 int len = 0;
953 int existing_len = 0;
954 int line = __LINE__;
955 static int logged = 0;
956
957 char *arg_string = NULL;
958
959 if (argc == 0 || argv == NULL || logged) {
960 return;
961 }
962
963 logged = 1;
964
965 for (; lpc < argc; lpc++) {
966 if (argv[lpc] == NULL) {
967 break;
968 }
969
970 len = 2 + strlen(argv[lpc]);
971 arg_string = realloc_safe(arg_string, len + existing_len);
972 existing_len += sprintf(arg_string + existing_len, "%s ", argv[lpc]);
973 }
974
975 qb_log_from_external_source(__func__, __FILE__, ARGS_FMT, LOG_NOTICE, line, 0, arg_string);
976
977 free(arg_string);
978 }
979
980 const char *
981 pcmk_errorname(int rc)
982 {
983 int error = ABS(rc);
984
985 switch (error) {
986 case E2BIG: return "E2BIG";
987 case EACCES: return "EACCES";
988 case EADDRINUSE: return "EADDRINUSE";
989 case EADDRNOTAVAIL: return "EADDRNOTAVAIL";
990 case EAFNOSUPPORT: return "EAFNOSUPPORT";
991 case EAGAIN: return "EAGAIN";
992 case EALREADY: return "EALREADY";
993 case EBADF: return "EBADF";
994 case EBADMSG: return "EBADMSG";
995 case EBUSY: return "EBUSY";
996 case ECANCELED: return "ECANCELED";
997 case ECHILD: return "ECHILD";
998 case ECOMM: return "ECOMM";
999 case ECONNABORTED: return "ECONNABORTED";
1000 case ECONNREFUSED: return "ECONNREFUSED";
1001 case ECONNRESET: return "ECONNRESET";
1002
1003 case EDESTADDRREQ: return "EDESTADDRREQ";
1004 case EDOM: return "EDOM";
1005 case EDQUOT: return "EDQUOT";
1006 case EEXIST: return "EEXIST";
1007 case EFAULT: return "EFAULT";
1008 case EFBIG: return "EFBIG";
1009 case EHOSTDOWN: return "EHOSTDOWN";
1010 case EHOSTUNREACH: return "EHOSTUNREACH";
1011 case EIDRM: return "EIDRM";
1012 case EILSEQ: return "EILSEQ";
1013 case EINPROGRESS: return "EINPROGRESS";
1014 case EINTR: return "EINTR";
1015 case EINVAL: return "EINVAL";
1016 case EIO: return "EIO";
1017 case EISCONN: return "EISCONN";
1018 case EISDIR: return "EISDIR";
1019 case ELIBACC: return "ELIBACC";
1020 case ELOOP: return "ELOOP";
1021 case EMFILE: return "EMFILE";
1022 case EMLINK: return "EMLINK";
1023 case EMSGSIZE: return "EMSGSIZE";
1024 case EMULTIHOP: return "EMULTIHOP";
1025 case ENAMETOOLONG: return "ENAMETOOLONG";
1026 case ENETDOWN: return "ENETDOWN";
1027 case ENETRESET: return "ENETRESET";
1028 case ENETUNREACH: return "ENETUNREACH";
1029 case ENFILE: return "ENFILE";
1030 case ENOBUFS: return "ENOBUFS";
1031 case ENODATA: return "ENODATA";
1032 case ENODEV: return "ENODEV";
1033 case ENOENT: return "ENOENT";
1034 case ENOEXEC: return "ENOEXEC";
1035 case ENOKEY: return "ENOKEY";
1036 case ENOLCK: return "ENOLCK";
1037 case ENOLINK: return "ENOLINK";
1038 case ENOMEM: return "ENOMEM";
1039 case ENOMSG: return "ENOMSG";
1040 case ENOPROTOOPT: return "ENOPROTOOPT";
1041 case ENOSPC: return "ENOSPC";
1042 case ENOSR: return "ENOSR";
1043 case ENOSTR: return "ENOSTR";
1044 case ENOSYS: return "ENOSYS";
1045 case ENOTBLK: return "ENOTBLK";
1046 case ENOTCONN: return "ENOTCONN";
1047 case ENOTDIR: return "ENOTDIR";
1048 case ENOTEMPTY: return "ENOTEMPTY";
1049 case ENOTSOCK: return "ENOTSOCK";
1050
1051 case ENOTTY: return "ENOTTY";
1052 case ENOTUNIQ: return "ENOTUNIQ";
1053 case ENXIO: return "ENXIO";
1054 case EOPNOTSUPP: return "EOPNOTSUPP";
1055 case EOVERFLOW: return "EOVERFLOW";
1056 case EPERM: return "EPERM";
1057 case EPFNOSUPPORT: return "EPFNOSUPPORT";
1058 case EPIPE: return "EPIPE";
1059 case EPROTO: return "EPROTO";
1060 case EPROTONOSUPPORT: return "EPROTONOSUPPORT";
1061 case EPROTOTYPE: return "EPROTOTYPE";
1062 case ERANGE: return "ERANGE";
1063 case EREMOTE: return "EREMOTE";
1064 case EREMOTEIO: return "EREMOTEIO";
1065
1066 case EROFS: return "EROFS";
1067 case ESHUTDOWN: return "ESHUTDOWN";
1068 case ESPIPE: return "ESPIPE";
1069 case ESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT";
1070 case ESRCH: return "ESRCH";
1071 case ESTALE: return "ESTALE";
1072 case ETIME: return "ETIME";
1073 case ETIMEDOUT: return "ETIMEDOUT";
1074 case ETXTBSY: return "ETXTBSY";
1075 case EUNATCH: return "EUNATCH";
1076 case EUSERS: return "EUSERS";
1077
1078 case EXDEV: return "EXDEV";
1079
1080 #ifdef EBADE
1081
1082 case EBADE: return "EBADE";
1083 case EBADFD: return "EBADFD";
1084 case EBADSLT: return "EBADSLT";
1085 case EDEADLOCK: return "EDEADLOCK";
1086 case EBADR: return "EBADR";
1087 case EBADRQC: return "EBADRQC";
1088 case ECHRNG: return "ECHRNG";
1089 #ifdef EISNAM
1090 case EISNAM: return "EISNAM";
1091 case EKEYEXPIRED: return "EKEYEXPIRED";
1092 case EKEYREJECTED: return "EKEYREJECTED";
1093 case EKEYREVOKED: return "EKEYREVOKED";
1094 #endif
1095 case EL2HLT: return "EL2HLT";
1096 case EL2NSYNC: return "EL2NSYNC";
1097 case EL3HLT: return "EL3HLT";
1098 case EL3RST: return "EL3RST";
1099 case ELIBBAD: return "ELIBBAD";
1100 case ELIBMAX: return "ELIBMAX";
1101 case ELIBSCN: return "ELIBSCN";
1102 case ELIBEXEC: return "ELIBEXEC";
1103 #ifdef ENOMEDIUM
1104 case ENOMEDIUM: return "ENOMEDIUM";
1105 case EMEDIUMTYPE: return "EMEDIUMTYPE";
1106 #endif
1107 case ENONET: return "ENONET";
1108 case ENOPKG: return "ENOPKG";
1109 case EREMCHG: return "EREMCHG";
1110 case ERESTART: return "ERESTART";
1111 case ESTRPIPE: return "ESTRPIPE";
1112 #ifdef EUCLEAN
1113 case EUCLEAN: return "EUCLEAN";
1114 #endif
1115 case EXFULL: return "EXFULL";
1116 #endif
1117
1118 case pcmk_err_generic: return "pcmk_err_generic";
1119 case pcmk_err_no_quorum: return "pcmk_err_no_quorum";
1120 case pcmk_err_schema_validation: return "pcmk_err_schema_validation";
1121 case pcmk_err_transform_failed: return "pcmk_err_transform_failed";
1122 case pcmk_err_old_data: return "pcmk_err_old_data";
1123 case pcmk_err_diff_failed: return "pcmk_err_diff_failed";
1124 case pcmk_err_diff_resync: return "pcmk_err_diff_resync";
1125 case pcmk_err_cib_modified: return "pcmk_err_cib_modified";
1126 case pcmk_err_cib_backup: return "pcmk_err_cib_backup";
1127 case pcmk_err_cib_save: return "pcmk_err_cib_save";
1128 case pcmk_err_cib_corrupt: return "pcmk_err_cib_corrupt";
1129 }
1130 return "Unknown";
1131 }
1132
1133
1134 const char *
1135 pcmk_strerror(int rc)
1136 {
1137 int error = abs(rc);
1138
1139 if (error == 0) {
1140 return "OK";
1141 } else if (error < PCMK_ERROR_OFFSET) {
1142 return strerror(error);
1143 }
1144
1145 switch (error) {
1146 case pcmk_err_generic:
1147 return "Generic Pacemaker error";
1148 case pcmk_err_no_quorum:
1149 return "Operation requires quorum";
1150 case pcmk_err_schema_validation:
1151 return "Update does not conform to the configured schema";
1152 case pcmk_err_transform_failed:
1153 return "Schema transform failed";
1154 case pcmk_err_old_data:
1155 return "Update was older than existing configuration";
1156 case pcmk_err_diff_failed:
1157 return "Application of an update diff failed";
1158 case pcmk_err_diff_resync:
1159 return "Application of an update diff failed, requesting a full refresh";
1160 case pcmk_err_cib_modified:
1161 return "The on-disk configuration was manually modified";
1162 case pcmk_err_cib_backup:
1163 return "Could not archive the previous configuration";
1164 case pcmk_err_cib_save:
1165 return "Could not save the new configuration to disk";
1166 case pcmk_err_cib_corrupt:
1167 return "Could not parse on-disk configuration";
1168
1169 case pcmk_err_schema_unchanged:
1170 return "Schema is already the latest available";
1171
1172
1173
1174 case ENOTUNIQ:
1175 return "Name not unique on network";
1176
1177 case ECOMM:
1178 return "Communication error on send";
1179
1180 case ELIBACC:
1181 return "Can not access a needed shared library";
1182
1183 case EREMOTEIO:
1184 return "Remote I/O error";
1185
1186 case EUNATCH:
1187 return "Protocol driver not attached";
1188
1189 case ENOKEY:
1190 return "Required key not available";
1191 }
1192
1193 crm_err("Unknown error code: %d", rc);
1194 return "Unknown error";
1195 }
1196
1197 const char *
1198 bz2_strerror(int rc)
1199 {
1200
1201 switch (rc) {
1202 case BZ_OK:
1203 case BZ_RUN_OK:
1204 case BZ_FLUSH_OK:
1205 case BZ_FINISH_OK:
1206 case BZ_STREAM_END:
1207 return "Ok";
1208 case BZ_CONFIG_ERROR:
1209 return "libbz2 has been improperly compiled on your platform";
1210 case BZ_SEQUENCE_ERROR:
1211 return "library functions called in the wrong order";
1212 case BZ_PARAM_ERROR:
1213 return "parameter is out of range or otherwise incorrect";
1214 case BZ_MEM_ERROR:
1215 return "memory allocation failed";
1216 case BZ_DATA_ERROR:
1217 return "data integrity error is detected during decompression";
1218 case BZ_DATA_ERROR_MAGIC:
1219 return "the compressed stream does not start with the correct magic bytes";
1220 case BZ_IO_ERROR:
1221 return "error reading or writing in the compressed file";
1222 case BZ_UNEXPECTED_EOF:
1223 return "compressed file finishes before the logical end of stream is detected";
1224 case BZ_OUTBUFF_FULL:
1225 return "output data will not fit into the buffer provided";
1226 }
1227 return "Unknown error";
1228 }
1229
1230 void
1231 crm_log_output_fn(const char *file, const char *function, int line, int level, const char *prefix,
1232 const char *output)
1233 {
1234 const char *next = NULL;
1235 const char *offset = NULL;
1236
1237 if (output == NULL) {
1238 level = LOG_DEBUG;
1239 output = "-- empty --";
1240 }
1241
1242 next = output;
1243 do {
1244 offset = next;
1245 next = strchrnul(offset, '\n');
1246 do_crm_log_alias(level, file, function, line, "%s [ %.*s ]", prefix,
1247 (int)(next - offset), offset);
1248 if (next[0] != 0) {
1249 next++;
1250 }
1251
1252 } while (next != NULL && next[0] != 0);
1253 }
1254
1255 char *
1256 crm_strdup_printf (char const *format, ...)
1257 {
1258 va_list ap;
1259 int len = 0;
1260 char *string = NULL;
1261
1262 va_start(ap, format);
1263
1264 len = vasprintf (&string, format, ap);
1265 CRM_ASSERT(len > 0);
1266
1267 va_end(ap);
1268 return string;
1269 }