pacemaker  1.1.24-3850484742
Scalable High-Availability cluster resource manager
logging.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2020 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <crm_internal.h>
22 
23 #include <sys/param.h>
24 #include <sys/types.h>
25 #include <sys/wait.h>
26 #include <sys/stat.h>
27 #include <sys/utsname.h>
28 
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <limits.h>
34 #include <ctype.h>
35 #include <pwd.h>
36 #include <grp.h>
37 #include <time.h>
38 #include <libgen.h>
39 #include <signal.h>
40 #include <bzlib.h>
41 
42 #include <qb/qbdefs.h>
43 
44 #include <crm/crm.h>
45 #include <crm/common/mainloop.h>
46 
47 unsigned int crm_log_priority = LOG_NOTICE;
48 unsigned int crm_log_level = LOG_INFO;
49 static gboolean crm_tracing_enabled(void);
50 unsigned int crm_trace_nonlog = 0;
51 bool crm_is_daemon = 0;
52 
53 #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER
54 GLogFunc glib_log_default;
55 
56 static void
57 crm_glib_handler(const gchar * log_domain, GLogLevelFlags flags, const gchar * message,
58  gpointer user_data)
59 {
60  int log_level = LOG_WARNING;
61  GLogLevelFlags msg_level = (flags & G_LOG_LEVEL_MASK);
62  static struct qb_log_callsite *glib_cs = NULL;
63 
64  if (glib_cs == NULL) {
65  glib_cs = qb_log_callsite_get(__FUNCTION__, __FILE__, "glib-handler", LOG_DEBUG, __LINE__, crm_trace_nonlog);
66  }
67 
68 
69  switch (msg_level) {
70  case G_LOG_LEVEL_CRITICAL:
71  log_level = LOG_CRIT;
72 
73  if (crm_is_callsite_active(glib_cs, LOG_DEBUG, 0) == FALSE) {
74  /* log and record how we got here */
75  crm_abort(__FILE__, __FUNCTION__, __LINE__, message, TRUE, TRUE);
76  }
77  break;
78 
79  case G_LOG_LEVEL_ERROR:
80  log_level = LOG_ERR;
81  break;
82  case G_LOG_LEVEL_MESSAGE:
83  log_level = LOG_NOTICE;
84  break;
85  case G_LOG_LEVEL_INFO:
86  log_level = LOG_INFO;
87  break;
88  case G_LOG_LEVEL_DEBUG:
89  log_level = LOG_DEBUG;
90  break;
91 
92  case G_LOG_LEVEL_WARNING:
93  case G_LOG_FLAG_RECURSION:
94  case G_LOG_FLAG_FATAL:
95  case G_LOG_LEVEL_MASK:
96  log_level = LOG_WARNING;
97  break;
98  }
99 
100  do_crm_log(log_level, "%s: %s", log_domain, message);
101 }
102 #endif
103 
104 #ifndef NAME_MAX
105 # define NAME_MAX 256
106 #endif
107 
108 static void
109 crm_trigger_blackbox(int nsig)
110 {
111  if(nsig == SIGTRAP) {
112  /* Turn it on if it wasn't already */
113  crm_enable_blackbox(nsig);
114  }
115  crm_write_blackbox(nsig, NULL);
116 }
117 
118 const char *
119 daemon_option(const char *option)
120 {
121  char env_name[NAME_MAX];
122  const char *value = NULL;
123 
124  snprintf(env_name, NAME_MAX, "PCMK_%s", option);
125  value = getenv(env_name);
126  if (value != NULL) {
127  crm_trace("Found %s = %s", env_name, value);
128  return value;
129  }
130 
131  snprintf(env_name, NAME_MAX, "HA_%s", option);
132  value = getenv(env_name);
133  if (value != NULL) {
134  crm_trace("Found %s = %s", env_name, value);
135  return value;
136  }
137 
138  crm_trace("Nothing found for %s", option);
139  return NULL;
140 }
141 
142 void
143 set_daemon_option(const char *option, const char *value)
144 {
145  char env_name[NAME_MAX];
146 
147  snprintf(env_name, NAME_MAX, "PCMK_%s", option);
148  if (value) {
149  crm_trace("Setting %s to %s", env_name, value);
150  setenv(env_name, value, 1);
151  } else {
152  crm_trace("Unsetting %s", env_name);
153  unsetenv(env_name);
154  }
155 
156  snprintf(env_name, NAME_MAX, "HA_%s", option);
157  if (value) {
158  crm_trace("Setting %s to %s", env_name, value);
159  setenv(env_name, value, 1);
160  } else {
161  crm_trace("Unsetting %s", env_name);
162  unsetenv(env_name);
163  }
164 }
165 
166 gboolean
167 daemon_option_enabled(const char *daemon, const char *option)
168 {
169  const char *value = daemon_option(option);
170 
171  if (value != NULL && crm_is_true(value)) {
172  return TRUE;
173 
174  } else if (value != NULL && strstr(value, daemon)) {
175  return TRUE;
176  }
177 
178  return FALSE;
179 }
180 
181 void
183 {
184 #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER
185  g_log_set_default_handler(glib_log_default, NULL);
186 #endif
187 }
188 
189 #define FMT_MAX 256
190 static void
191 set_format_string(int method, const char *daemon)
192 {
193  int offset = 0;
194  char fmt[FMT_MAX];
195 
196  if (method > QB_LOG_STDERR) {
197  /* When logging to a file */
198  struct utsname res;
199 
200  if (uname(&res) == 0) {
201  offset +=
202  snprintf(fmt + offset, FMT_MAX - offset, "%%t [%lu] %s %10s: ",
203  (unsigned long) getpid(), res.nodename, daemon);
204  } else {
205  offset += snprintf(fmt + offset, FMT_MAX - offset, "%%t [%lu] %10s: ",
206  (unsigned long) getpid(), daemon);
207  }
208  }
209 
210  if (method == QB_LOG_SYSLOG) {
211  offset += snprintf(fmt + offset, FMT_MAX - offset, "%%g %%-7p: %%b");
212  crm_extended_logging(method, QB_FALSE);
213  } else if (crm_tracing_enabled()) {
214  offset += snprintf(fmt + offset, FMT_MAX - offset, "(%%-12f:%%5l %%g) %%-7p: %%n:\t%%b");
215  } else {
216  offset += snprintf(fmt + offset, FMT_MAX - offset, "%%g %%-7p: %%n:\t%%b");
217  }
218 
219  CRM_LOG_ASSERT(offset > 0);
220  qb_log_format_set(method, fmt);
221 }
222 
223 gboolean
224 crm_add_logfile(const char *filename)
225 {
226  bool is_default = false;
227  static int default_fd = -1;
228  static gboolean have_logfile = FALSE;
229 
230  /* @COMPAT This should be CRM_LOG_DIR "/pacemaker.log". We aren't changing
231  * it yet because it will be a significant user-visible change to publicize.
232  */
233  const char *default_logfile = "/var/log/pacemaker.log";
234 
235  struct stat parent;
236  int fd = 0, rc = 0;
237  FILE *logfile = NULL;
238  char *parent_dir = NULL;
239  char *filename_cp;
240 
241  if (filename == NULL && have_logfile == FALSE) {
242  filename = default_logfile;
243  }
244 
245  if (filename == NULL) {
246  return FALSE; /* Nothing to do */
247  } else if(safe_str_eq(filename, "none")) {
248  return FALSE; /* Nothing to do */
249  } else if(safe_str_eq(filename, "/dev/null")) {
250  return FALSE; /* Nothing to do */
251  } else if(safe_str_eq(filename, default_logfile)) {
252  is_default = TRUE;
253  }
254 
255  if(is_default && default_fd >= 0) {
256  return TRUE; /* Nothing to do */
257  }
258 
259  /* Check the parent directory */
260  filename_cp = strdup(filename);
261  parent_dir = dirname(filename_cp);
262  rc = stat(parent_dir, &parent);
263 
264  if (rc != 0) {
265  crm_err("Directory '%s' does not exist: logging to '%s' is disabled", parent_dir, filename);
266  free(filename_cp);
267  return FALSE;
268  }
269  free(filename_cp);
270 
271  errno = 0;
272  logfile = fopen(filename, "a");
273  if(logfile == NULL) {
274  crm_err("%s (%d): Logging to '%s' as uid=%u, gid=%u is disabled",
275  pcmk_strerror(errno), errno, filename, geteuid(), getegid());
276  return FALSE;
277  }
278 
279  /* Check/Set permissions if we're root */
280  if (geteuid() == 0) {
281  struct stat st;
282  uid_t pcmk_uid = 0;
283  gid_t pcmk_gid = 0;
284  gboolean fix = FALSE;
285  int logfd = fileno(logfile);
286 
287  rc = fstat(logfd, &st);
288  if (rc < 0) {
289  crm_perror(LOG_WARNING, "Cannot stat %s", filename);
290  fclose(logfile);
291  return FALSE;
292  }
293 
294  if(crm_user_lookup(CRM_DAEMON_USER, &pcmk_uid, &pcmk_gid) == 0) {
295  if (st.st_gid != pcmk_gid) {
296  /* Wrong group */
297  fix = TRUE;
298  } else if ((st.st_mode & S_IRWXG) != (S_IRGRP | S_IWGRP)) {
299  /* Not read/writable by the correct group */
300  fix = TRUE;
301  }
302  }
303 
304  if (fix) {
305  rc = fchown(logfd, pcmk_uid, pcmk_gid);
306  if (rc < 0) {
307  crm_warn("Cannot change the ownership of %s to user %s and gid %d",
308  filename, CRM_DAEMON_USER, pcmk_gid);
309  }
310 
311  rc = fchmod(logfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
312  if (rc < 0) {
313  crm_warn("Cannot change the mode of %s to rw-rw----", filename);
314  }
315 
316  fprintf(logfile, "Set r/w permissions for uid=%d, gid=%d on %s\n",
317  pcmk_uid, pcmk_gid, filename);
318  if (fflush(logfile) < 0 || fsync(logfd) < 0) {
319  crm_err("Couldn't write out logfile: %s", filename);
320  }
321  }
322  }
323 
324  /* Close and reopen with libqb */
325  fclose(logfile);
326  fd = qb_log_file_open(filename);
327 
328  if (fd < 0) {
329  crm_perror(LOG_WARNING, "Couldn't send additional logging to %s", filename);
330  return FALSE;
331  }
332 
333  if(is_default) {
334  default_fd = fd;
335 
336  } else if(default_fd >= 0) {
337  crm_notice("Switching to %s", filename);
338  qb_log_ctl(default_fd, QB_LOG_CONF_ENABLED, QB_FALSE);
339  }
340 
341  crm_notice("Additional logging available in %s", filename);
342  qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_TRUE);
343  /* qb_log_ctl(fd, QB_LOG_CONF_FILE_SYNC, 1); Turn on synchronous writes */
344 
345  /* Enable callsites */
347  have_logfile = TRUE;
348 
349  return TRUE;
350 }
351 
352 static int blackbox_trigger = 0;
353 static char *blackbox_file_prefix = NULL;
354 
355 #ifdef QB_FEATURE_LOG_HIRES_TIMESTAMPS
356 typedef struct timespec *log_time_t;
357 #else
358 typedef time_t log_time_t;
359 #endif
360 
361 static void
362 blackbox_logger(int32_t t, struct qb_log_callsite *cs, log_time_t timestamp,
363  const char *msg)
364 {
365  if(cs && cs->priority < LOG_ERR) {
366  crm_write_blackbox(SIGTRAP, cs); /* Bypass the over-dumping logic */
367  } else {
368  crm_write_blackbox(0, cs);
369  }
370 }
371 
372 static void
373 crm_control_blackbox(int nsig, bool enable)
374 {
375  int lpc = 0;
376 
377  if (blackbox_file_prefix == NULL) {
378  pid_t pid = getpid();
379 
380  blackbox_file_prefix = malloc(NAME_MAX);
381  snprintf(blackbox_file_prefix, NAME_MAX, "%s/%s-%lu",
382  CRM_BLACKBOX_DIR, crm_system_name, (unsigned long) pid);
383  }
384 
385  if (enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
386  qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 5 * 1024 * 1024); /* Any size change drops existing entries */
387  qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE); /* Setting the size seems to disable it */
388 
389  /* Enable synchronous logging */
390  for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
391  qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_TRUE);
392  }
393 
394  crm_notice("Initiated blackbox recorder: %s", blackbox_file_prefix);
395 
396  /* Save to disk on abnormal termination */
397  crm_signal(SIGSEGV, crm_trigger_blackbox);
398  crm_signal(SIGABRT, crm_trigger_blackbox);
399  crm_signal(SIGILL, crm_trigger_blackbox);
400  crm_signal(SIGBUS, crm_trigger_blackbox);
401  crm_signal(SIGFPE, crm_trigger_blackbox);
402 
404 
405  blackbox_trigger = qb_log_custom_open(blackbox_logger, NULL, NULL, NULL);
406  qb_log_ctl(blackbox_trigger, QB_LOG_CONF_ENABLED, QB_TRUE);
407  crm_trace("Trigger: %d is %d %d", blackbox_trigger,
408  qb_log_ctl(blackbox_trigger, QB_LOG_CONF_STATE_GET, 0), QB_LOG_STATE_ENABLED);
409 
411 
412  } else if (!enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
413  qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
414 
415  /* Disable synchronous logging again when the blackbox is disabled */
416  for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
417  qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_FALSE);
418  }
419  }
420 }
421 
422 void
424 {
425  crm_control_blackbox(nsig, TRUE);
426 }
427 
428 void
430 {
431  crm_control_blackbox(nsig, FALSE);
432 }
433 
434 void
435 crm_write_blackbox(int nsig, struct qb_log_callsite *cs)
436 {
437  static int counter = 1;
438  static time_t last = 0;
439 
440  char buffer[NAME_MAX];
441  time_t now = time(NULL);
442 
443  if (blackbox_file_prefix == NULL) {
444  return;
445  }
446 
447  switch (nsig) {
448  case 0:
449  case SIGTRAP:
450  /* The graceful case - such as assertion failure or user request */
451 
452  if (nsig == 0 && now == last) {
453  /* Prevent over-dumping */
454  return;
455  }
456 
457  snprintf(buffer, NAME_MAX, "%s.%d", blackbox_file_prefix, counter++);
458  if (nsig == SIGTRAP) {
459  crm_notice("Blackbox dump requested, please see %s for contents", buffer);
460 
461  } else if (cs) {
462  syslog(LOG_NOTICE,
463  "Problem detected at %s:%d (%s), please see %s for additional details",
464  cs->function, cs->lineno, cs->filename, buffer);
465  } else {
466  crm_notice("Problem detected, please see %s for additional details", buffer);
467  }
468 
469  last = now;
470  qb_log_blackbox_write_to_file(buffer);
471 
472  /* Flush the existing contents
473  * A size change would also work
474  */
475  qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
476  qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
477  break;
478 
479  default:
480  /* Do as little as possible, just try to get what we have out
481  * We logged the filename when the blackbox was enabled
482  */
483  crm_signal(nsig, SIG_DFL);
484  qb_log_blackbox_write_to_file(blackbox_file_prefix);
485  qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
486  raise(nsig);
487  break;
488  }
489 }
490 
491 gboolean
492 crm_log_cli_init(const char *entity)
493 {
494  return crm_log_init(entity, LOG_ERR, FALSE, FALSE, 0, NULL, TRUE);
495 }
496 
497 static const char *
498 crm_quark_to_string(uint32_t tag)
499 {
500  const char *text = g_quark_to_string(tag);
501 
502  if (text) {
503  return text;
504  }
505  return "";
506 }
507 
508 static void
509 crm_log_filter_source(int source, const char *trace_files, const char *trace_fns,
510  const char *trace_fmts, const char *trace_tags, const char *trace_blackbox,
511  struct qb_log_callsite *cs)
512 {
513  if (qb_log_ctl(source, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
514  return;
515  } else if (cs->tags != crm_trace_nonlog && source == QB_LOG_BLACKBOX) {
516  /* Blackbox gets everything if enabled */
517  qb_bit_set(cs->targets, source);
518 
519  } else if (source == blackbox_trigger && blackbox_trigger > 0) {
520  /* Should this log message result in the blackbox being dumped */
521  if (cs->priority <= LOG_ERR) {
522  qb_bit_set(cs->targets, source);
523 
524  } else if (trace_blackbox) {
525  char *key = crm_strdup_printf("%s:%d", cs->function, cs->lineno);
526 
527  if (strstr(trace_blackbox, key) != NULL) {
528  qb_bit_set(cs->targets, source);
529  }
530  free(key);
531  }
532 
533  } else if (source == QB_LOG_SYSLOG) { /* No tracing to syslog */
534  if (cs->priority <= crm_log_priority && cs->priority <= crm_log_level) {
535  qb_bit_set(cs->targets, source);
536  }
537  /* Log file tracing options... */
538  } else if (cs->priority <= crm_log_level) {
539  qb_bit_set(cs->targets, source);
540  } else if (trace_files && strstr(trace_files, cs->filename) != NULL) {
541  qb_bit_set(cs->targets, source);
542  } else if (trace_fns && strstr(trace_fns, cs->function) != NULL) {
543  qb_bit_set(cs->targets, source);
544  } else if (trace_fmts && strstr(trace_fmts, cs->format) != NULL) {
545  qb_bit_set(cs->targets, source);
546  } else if (trace_tags
547  && cs->tags != 0
548  && cs->tags != crm_trace_nonlog && g_quark_to_string(cs->tags) != NULL) {
549  qb_bit_set(cs->targets, source);
550  }
551 }
552 
553 static void
554 crm_log_filter(struct qb_log_callsite *cs)
555 {
556  int lpc = 0;
557  static int need_init = 1;
558  static const char *trace_fns = NULL;
559  static const char *trace_tags = NULL;
560  static const char *trace_fmts = NULL;
561  static const char *trace_files = NULL;
562  static const char *trace_blackbox = NULL;
563 
564  if (need_init) {
565  need_init = 0;
566  trace_fns = getenv("PCMK_trace_functions");
567  trace_fmts = getenv("PCMK_trace_formats");
568  trace_tags = getenv("PCMK_trace_tags");
569  trace_files = getenv("PCMK_trace_files");
570  trace_blackbox = getenv("PCMK_trace_blackbox");
571 
572  if (trace_tags != NULL) {
573  uint32_t tag;
574  char token[500];
575  const char *offset = NULL;
576  const char *next = trace_tags;
577 
578  do {
579  offset = next;
580  next = strchrnul(offset, ',');
581  snprintf(token, sizeof(token), "%.*s", (int)(next - offset), offset);
582 
583  tag = g_quark_from_string(token);
584  crm_info("Created GQuark %u from token '%s' in '%s'", tag, token, trace_tags);
585 
586  if (next[0] != 0) {
587  next++;
588  }
589 
590  } while (next != NULL && next[0] != 0);
591  }
592  }
593 
594  cs->targets = 0; /* Reset then find targets to enable */
595  for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
596  crm_log_filter_source(lpc, trace_files, trace_fns, trace_fmts, trace_tags, trace_blackbox,
597  cs);
598  }
599 }
600 
601 gboolean
602 crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
603 {
604  gboolean refilter = FALSE;
605 
606  if (cs == NULL) {
607  return FALSE;
608  }
609 
610  if (cs->priority != level) {
611  cs->priority = level;
612  refilter = TRUE;
613  }
614 
615  if (cs->tags != tags) {
616  cs->tags = tags;
617  refilter = TRUE;
618  }
619 
620  if (refilter) {
621  crm_log_filter(cs);
622  }
623 
624  if (cs->targets == 0) {
625  return FALSE;
626  }
627  return TRUE;
628 }
629 
630 void
632 {
633  static gboolean log = TRUE;
634 
635  if (log) {
636  log = FALSE;
637  crm_debug
638  ("Enabling callsites based on priority=%d, files=%s, functions=%s, formats=%s, tags=%s",
639  crm_log_level, getenv("PCMK_trace_files"), getenv("PCMK_trace_functions"),
640  getenv("PCMK_trace_formats"), getenv("PCMK_trace_tags"));
641  }
642  qb_log_filter_fn_set(crm_log_filter);
643 }
644 
645 static gboolean
646 crm_tracing_enabled(void)
647 {
648  if (crm_log_level >= LOG_TRACE) {
649  return TRUE;
650  } else if (getenv("PCMK_trace_files") || getenv("PCMK_trace_functions")
651  || getenv("PCMK_trace_formats") || getenv("PCMK_trace_tags")) {
652  return TRUE;
653  }
654  return FALSE;
655 }
656 
657 static int
658 crm_priority2int(const char *name)
659 {
660  struct syslog_names {
661  const char *name;
662  int priority;
663  };
664  static struct syslog_names p_names[] = {
665  {"emerg", LOG_EMERG},
666  {"alert", LOG_ALERT},
667  {"crit", LOG_CRIT},
668  {"error", LOG_ERR},
669  {"warning", LOG_WARNING},
670  {"notice", LOG_NOTICE},
671  {"info", LOG_INFO},
672  {"debug", LOG_DEBUG},
673  {NULL, -1}
674  };
675  int lpc;
676 
677  for (lpc = 0; name != NULL && p_names[lpc].name != NULL; lpc++) {
678  if (crm_str_eq(p_names[lpc].name, name, TRUE)) {
679  return p_names[lpc].priority;
680  }
681  }
682  return crm_log_priority;
683 }
684 
685 
686 static void
687 crm_identity(const char *entity, int argc, char **argv)
688 {
689  if(crm_system_name != NULL) {
690  /* Nothing to do */
691 
692  } else if (entity) {
693  free(crm_system_name);
694  crm_system_name = strdup(entity);
695 
696  } else if (argc > 0 && argv != NULL) {
697  char *mutable = strdup(argv[0]);
698  char *modified = basename(mutable);
699 
700  if (strstr(modified, "lt-") == modified) {
701  modified += 3;
702  }
703 
704  free(crm_system_name);
705  crm_system_name = strdup(modified);
706  free(mutable);
707 
708  } else if (crm_system_name == NULL) {
709  crm_system_name = strdup("Unknown");
710  }
711 
712  setenv("PCMK_service", crm_system_name, 1);
713 }
714 
715 
716 void
717 crm_log_preinit(const char *entity, int argc, char **argv)
718 {
719  /* Configure libqb logging with nothing turned on */
720 
721  int lpc = 0;
722  int32_t qb_facility = 0;
723 
724  static bool have_logging = FALSE;
725 
726  if(have_logging == FALSE) {
727  have_logging = TRUE;
728 
729  crm_xml_init(); /* Sets buffer allocation strategy */
730 
731  if (crm_trace_nonlog == 0) {
732  crm_trace_nonlog = g_quark_from_static_string("Pacemaker non-logging tracepoint");
733  }
734 
735  umask(S_IWGRP | S_IWOTH | S_IROTH);
736 
737  /* Redirect messages from glib functions to our handler */
738 #ifdef HAVE_G_LOG_SET_DEFAULT_HANDLER
739  glib_log_default = g_log_set_default_handler(crm_glib_handler, NULL);
740 #endif
741 
742  /* and for good measure... - this enum is a bit field (!) */
743  g_log_set_always_fatal((GLogLevelFlags) 0); /*value out of range */
744 
745  /* Who do we log as */
746  crm_identity(entity, argc, argv);
747 
748  qb_facility = qb_log_facility2int("local0");
749  qb_log_init(crm_system_name, qb_facility, LOG_ERR);
750  crm_log_level = LOG_CRIT;
751 
752  /* Nuke any syslog activity until it's asked for */
753  qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
754 
755  /* Set format strings and disable threading
756  * Pacemaker and threads do not mix well (due to the amount of forking)
757  */
758  qb_log_tags_stringify_fn_set(crm_quark_to_string);
759  for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
760  qb_log_ctl(lpc, QB_LOG_CONF_THREADED, QB_FALSE);
761  set_format_string(lpc, crm_system_name);
762  }
763  }
764 }
765 
766 gboolean
767 crm_log_init(const char *entity, uint8_t level, gboolean daemon, gboolean to_stderr,
768  int argc, char **argv, gboolean quiet)
769 {
770  const char *syslog_priority = NULL;
771  const char *logfile = daemon_option("logfile");
772  const char *facility = daemon_option("logfacility");
773  const char *f_copy = facility;
774 
776  crm_log_preinit(entity, argc, argv);
777 
778  if(level > crm_log_level) {
779  crm_log_level = level;
780  }
781 
782  /* Should we log to syslog */
783  if (facility == NULL) {
784  if(crm_is_daemon) {
785  facility = "daemon";
786  } else {
787  facility = "none";
788  }
789  set_daemon_option("logfacility", facility);
790  }
791 
792  if (safe_str_eq(facility, "none")) {
793  quiet = TRUE;
794 
795 
796  } else {
797  qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, qb_log_facility2int(facility));
798  }
799 
800  if (daemon_option_enabled(crm_system_name, "debug")) {
801  /* Override the default setting */
802  crm_log_level = LOG_DEBUG;
803  }
804 
805  /* What lower threshold do we have for sending to syslog */
806  syslog_priority = daemon_option("logpriority");
807  if(syslog_priority) {
808  int priority = crm_priority2int(syslog_priority);
809  crm_log_priority = priority;
810  qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE, "*", priority);
811  } else {
812  qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE, "*", LOG_NOTICE);
813  }
814 
815  if (!quiet) {
816  /* Nuke any syslog activity */
817  qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
818  }
819 
820  /* Should we log to stderr */
821  if (daemon_option_enabled(crm_system_name, "stderr")) {
822  /* Override the default setting */
823  to_stderr = TRUE;
824  }
825  crm_enable_stderr(to_stderr);
826 
827  /* Should we log to a file */
828  if (safe_str_eq("none", logfile)) {
829  /* No soup^Hlogs for you! */
830  } else if(crm_is_daemon) {
831  /* The daemons always get a log file, unless explicitly set to configured 'none' */
832  crm_add_logfile(logfile);
833  } else if(logfile) {
834  crm_add_logfile(logfile);
835  }
836 
839  }
840 
841  /* Summary */
842  crm_trace("Quiet: %d, facility %s", quiet, f_copy);
843  daemon_option("logfile");
844  daemon_option("logfacility");
845 
847 
848  /* Ok, now we can start logging... */
849  if (quiet == FALSE && crm_is_daemon == FALSE) {
850  crm_log_args(argc, argv);
851  }
852 
853  if (crm_is_daemon) {
854  const char *user = getenv("USER");
855 
856  if (user != NULL && safe_str_neq(user, "root") && safe_str_neq(user, CRM_DAEMON_USER)) {
857  crm_trace("Not switching to corefile directory for %s", user);
858  crm_is_daemon = FALSE;
859  }
860  }
861 
862  if (crm_is_daemon) {
863  int user = getuid();
864  const char *base = CRM_CORE_DIR;
865  struct passwd *pwent = getpwuid(user);
866 
867  if (pwent == NULL) {
868  crm_perror(LOG_ERR, "Cannot get name for uid: %d", user);
869 
870  } else if (safe_str_neq(pwent->pw_name, "root")
871  && safe_str_neq(pwent->pw_name, CRM_DAEMON_USER)) {
872  crm_trace("Don't change active directory for regular user: %s", pwent->pw_name);
873 
874  } else if (chdir(base) < 0) {
875  crm_perror(LOG_INFO, "Cannot change active directory to %s", base);
876 
877  } else {
878  crm_info("Changed active directory to %s", base);
879 #if 0
880  {
881  char path[512];
882 
883  snprintf(path, 512, "%s-%lu", crm_system_name, (unsigned long) getpid());
884  mkdir(path, 0750);
885  chdir(path);
886  crm_info("Changed active directory to %s/%s/%s", base, pwent->pw_name, path);
887  }
888 #endif
889  }
890 
891  /* Original meanings from signal(7)
892  *
893  * Signal Value Action Comment
894  * SIGTRAP 5 Core Trace/breakpoint trap
895  * SIGUSR1 30,10,16 Term User-defined signal 1
896  * SIGUSR2 31,12,17 Term User-defined signal 2
897  *
898  * Our usage is as similar as possible
899  */
902  mainloop_add_signal(SIGTRAP, crm_trigger_blackbox);
903  }
904 
905  return TRUE;
906 }
907 
908 /* returns the old value */
909 unsigned int
910 set_crm_log_level(unsigned int level)
911 {
912  unsigned int old = crm_log_level;
913 
914  crm_log_level = level;
916  crm_trace("New log level: %d", level);
917  return old;
918 }
919 
920 void
921 crm_enable_stderr(int enable)
922 {
923  if (enable && qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
924  qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
926 
927  } else if (enable == FALSE) {
928  qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE);
929  }
930 }
931 
932 void
933 crm_bump_log_level(int argc, char **argv)
934 {
935  static int args = TRUE;
936  int level = crm_log_level;
937 
938  if (args && argc > 1) {
939  crm_log_args(argc, argv);
940  }
941 
942  if (qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
943  set_crm_log_level(level + 1);
944  }
945 
946  /* Enable after potentially logging the argstring, not before */
947  crm_enable_stderr(TRUE);
948 }
949 
950 unsigned int
952 {
953  return crm_log_level;
954 }
955 
956 #define ARGS_FMT "Invoked: %s"
957 void
958 crm_log_args(int argc, char **argv)
959 {
960  int lpc = 0;
961  int len = 0;
962  int existing_len = 0;
963  int line = __LINE__;
964  static int logged = 0;
965 
966  char *arg_string = NULL;
967 
968  if (argc == 0 || argv == NULL || logged) {
969  return;
970  }
971 
972  logged = 1;
973 
974  for (; lpc < argc; lpc++) {
975  if (argv[lpc] == NULL) {
976  break;
977  }
978 
979  len = 2 + strlen(argv[lpc]); /* +1 space, +1 EOS */
980  arg_string = realloc_safe(arg_string, len + existing_len);
981  existing_len += sprintf(arg_string + existing_len, "%s ", argv[lpc]);
982  }
983 
984  qb_log_from_external_source(__func__, __FILE__, ARGS_FMT, LOG_NOTICE, line, 0, arg_string);
985 
986  free(arg_string);
987 }
988 
989 // @COMPAT Legacy function return codes
990 
991 const char *
993 {
994  rc = abs(rc);
995  switch (rc) {
996  case pcmk_err_generic: return "pcmk_err_generic";
997  case pcmk_err_no_quorum: return "pcmk_err_no_quorum";
998  case pcmk_err_schema_validation: return "pcmk_err_schema_validation";
999  case pcmk_err_transform_failed: return "pcmk_err_transform_failed";
1000  case pcmk_err_old_data: return "pcmk_err_old_data";
1001  case pcmk_err_diff_failed: return "pcmk_err_diff_failed";
1002  case pcmk_err_diff_resync: return "pcmk_err_diff_resync";
1003  case pcmk_err_cib_modified: return "pcmk_err_cib_modified";
1004  case pcmk_err_cib_backup: return "pcmk_err_cib_backup";
1005  case pcmk_err_cib_save: return "pcmk_err_cib_save";
1006  case pcmk_err_cib_corrupt: return "pcmk_err_cib_corrupt";
1007  case pcmk_err_multiple: return "pcmk_err_multiple";
1008  case pcmk_err_node_unknown: return "pcmk_err_node_unknown";
1009  case pcmk_err_already: return "pcmk_err_already";
1010  case pcmk_err_bad_nvpair: return "pcmk_err_bad_nvpair";
1011  case pcmk_err_unknown_format: return "pcmk_err_unknown_format";
1012  default: return pcmk_rc_name(rc); // system errno
1013  }
1014 }
1015 
1016 const char *
1018 {
1019  if (rc == 0) {
1020  return "OK";
1021  }
1022 
1023  rc = abs(rc);
1024 
1025  // Of course rc > 0 ... unless someone passed INT_MIN as rc
1026  if ((rc > 0) && (rc < PCMK_ERROR_OFFSET)) {
1027  return strerror(rc);
1028  }
1029 
1030  switch (rc) {
1031  case pcmk_err_generic:
1032  return "Generic Pacemaker error";
1033  case pcmk_err_no_quorum:
1034  return "Operation requires quorum";
1036  return "Update does not conform to the configured schema";
1038  return "Schema transform failed";
1039  case pcmk_err_old_data:
1040  return "Update was older than existing configuration";
1041  case pcmk_err_diff_failed:
1042  return "Application of an update diff failed";
1043  case pcmk_err_diff_resync:
1044  return "Application of an update diff failed, requesting a full refresh";
1045  case pcmk_err_cib_modified:
1046  return "The on-disk configuration was manually modified";
1047  case pcmk_err_cib_backup:
1048  return "Could not archive the previous configuration";
1049  case pcmk_err_cib_save:
1050  return "Could not save the new configuration to disk";
1051  case pcmk_err_cib_corrupt:
1052  return "Could not parse on-disk configuration";
1053  case pcmk_err_multiple:
1054  return "Resource active on multiple nodes";
1055  case pcmk_err_node_unknown:
1056  return "Node not found";
1057  case pcmk_err_already:
1058  return "Situation already as requested";
1059  case pcmk_err_bad_nvpair:
1060  return "Bad name/value pair given";
1062  return "Schema is already the latest available";
1064  return "Unknown output format";
1065 
1066  /* The following cases will only be hit on systems for which they are non-standard */
1067  /* coverity[dead_error_condition] False positive on non-Linux */
1068  case ENOTUNIQ:
1069  return "Name not unique on network";
1070  /* coverity[dead_error_condition] False positive on non-Linux */
1071  case ECOMM:
1072  return "Communication error on send";
1073  /* coverity[dead_error_condition] False positive on non-Linux */
1074  case ELIBACC:
1075  return "Can not access a needed shared library";
1076  /* coverity[dead_error_condition] False positive on non-Linux */
1077  case EREMOTEIO:
1078  return "Remote I/O error";
1079  /* coverity[dead_error_condition] False positive on non-Linux */
1080  case EUNATCH:
1081  return "Protocol driver not attached";
1082  /* coverity[dead_error_condition] False positive on non-Linux */
1083  case ENOKEY:
1084  return "Required key not available";
1085  }
1086  crm_err("Unknown error code: %d", rc);
1087  return "Unknown error";
1088 }
1089 
1090 // Standard Pacemaker API return codes
1091 
1092 /* This array is used only for nonzero values of pcmk_rc_e. Its values must be
1093  * kept in the exact reverse order of the enum value numbering (i.e. add new
1094  * values to the end of the array).
1095  */
1096 static struct pcmk__rc_info {
1097  const char *name;
1098  const char *desc;
1099  int legacy_rc;
1100 } pcmk__rcs[] = {
1101  { "pcmk_rc_error",
1102  "Error",
1104  },
1105  { "pcmk_rc_unknown_format",
1106  "Unknown output format",
1108  },
1109  { "pcmk_rc_bad_nvpair",
1110  "Bad name/value pair given",
1112  },
1113  { "pcmk_rc_already",
1114  "Already in requested state",
1116  },
1117  { "pcmk_rc_node_unknown",
1118  "Node not found",
1120  },
1121  { "pcmk_rc_multiple",
1122  "Resource active on multiple nodes",
1124  },
1125  { "pcmk_rc_cib_corrupt",
1126  "Could not parse on-disk configuration",
1128  },
1129  { "pcmk_rc_cib_save",
1130  "Could not save new configuration to disk",
1132  },
1133  { "pcmk_rc_cib_backup",
1134  "Could not archive previous configuration",
1136  },
1137  { "pcmk_rc_cib_modified",
1138  "On-disk configuration was manually modified",
1140  },
1141  { "pcmk_rc_diff_resync",
1142  "Application of update diff failed, requesting full refresh",
1144  },
1145  { "pcmk_rc_diff_failed",
1146  "Application of update diff failed",
1148  },
1149  { "pcmk_rc_old_data",
1150  "Update was older than existing configuration",
1152  },
1153  { "pcmk_rc_transform_failed",
1154  "Schema transform failed",
1156  },
1157  { "pcmk_rc_schema_unchanged",
1158  "Schema is already the latest available",
1160  },
1161  { "pcmk_rc_schema_validation",
1162  "Update does not conform to the configured schema",
1164  },
1165  { "pcmk_rc_no_quorum",
1166  "Operation requires quorum",
1168  },
1169 };
1170 
1171 #define PCMK__N_RC (sizeof(pcmk__rcs) / sizeof(struct pcmk__rc_info))
1172 
1180 const char *
1182 {
1183  if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < PCMK__N_RC)) {
1184  return pcmk__rcs[pcmk_rc_error - rc].name;
1185  }
1186  switch (rc) {
1187  case pcmk_rc_ok: return "pcmk_rc_ok";
1188  case E2BIG: return "E2BIG";
1189  case EACCES: return "EACCES";
1190  case EADDRINUSE: return "EADDRINUSE";
1191  case EADDRNOTAVAIL: return "EADDRNOTAVAIL";
1192  case EAFNOSUPPORT: return "EAFNOSUPPORT";
1193  case EAGAIN: return "EAGAIN";
1194  case EALREADY: return "EALREADY";
1195  case EBADF: return "EBADF";
1196  case EBADMSG: return "EBADMSG";
1197  case EBUSY: return "EBUSY";
1198  case ECANCELED: return "ECANCELED";
1199  case ECHILD: return "ECHILD";
1200  case ECOMM: return "ECOMM";
1201  case ECONNABORTED: return "ECONNABORTED";
1202  case ECONNREFUSED: return "ECONNREFUSED";
1203  case ECONNRESET: return "ECONNRESET";
1204  /* case EDEADLK: return "EDEADLK"; */
1205  case EDESTADDRREQ: return "EDESTADDRREQ";
1206  case EDOM: return "EDOM";
1207  case EDQUOT: return "EDQUOT";
1208  case EEXIST: return "EEXIST";
1209  case EFAULT: return "EFAULT";
1210  case EFBIG: return "EFBIG";
1211  case EHOSTDOWN: return "EHOSTDOWN";
1212  case EHOSTUNREACH: return "EHOSTUNREACH";
1213  case EIDRM: return "EIDRM";
1214  case EILSEQ: return "EILSEQ";
1215  case EINPROGRESS: return "EINPROGRESS";
1216  case EINTR: return "EINTR";
1217  case EINVAL: return "EINVAL";
1218  case EIO: return "EIO";
1219  case EISCONN: return "EISCONN";
1220  case EISDIR: return "EISDIR";
1221  case ELIBACC: return "ELIBACC";
1222  case ELOOP: return "ELOOP";
1223  case EMFILE: return "EMFILE";
1224  case EMLINK: return "EMLINK";
1225  case EMSGSIZE: return "EMSGSIZE";
1226 #ifdef EMULTIHOP // Not available on OpenBSD
1227  case EMULTIHOP: return "EMULTIHOP";
1228 #endif
1229  case ENAMETOOLONG: return "ENAMETOOLONG";
1230  case ENETDOWN: return "ENETDOWN";
1231  case ENETRESET: return "ENETRESET";
1232  case ENETUNREACH: return "ENETUNREACH";
1233  case ENFILE: return "ENFILE";
1234  case ENOBUFS: return "ENOBUFS";
1235  case ENODATA: return "ENODATA";
1236  case ENODEV: return "ENODEV";
1237  case ENOENT: return "ENOENT";
1238  case ENOEXEC: return "ENOEXEC";
1239  case ENOKEY: return "ENOKEY";
1240  case ENOLCK: return "ENOLCK";
1241 #ifdef ENOLINK // Not available on OpenBSD
1242  case ENOLINK: return "ENOLINK";
1243 #endif
1244  case ENOMEM: return "ENOMEM";
1245  case ENOMSG: return "ENOMSG";
1246  case ENOPROTOOPT: return "ENOPROTOOPT";
1247  case ENOSPC: return "ENOSPC";
1248  case ENOSR: return "ENOSR";
1249  case ENOSTR: return "ENOSTR";
1250  case ENOSYS: return "ENOSYS";
1251  case ENOTBLK: return "ENOTBLK";
1252  case ENOTCONN: return "ENOTCONN";
1253  case ENOTDIR: return "ENOTDIR";
1254  case ENOTEMPTY: return "ENOTEMPTY";
1255  case ENOTSOCK: return "ENOTSOCK";
1256 #if ENOTSUP != EOPNOTSUPP
1257  case ENOTSUP: return "ENOTSUP";
1258 #endif
1259  case ENOTTY: return "ENOTTY";
1260  case ENOTUNIQ: return "ENOTUNIQ";
1261  case ENXIO: return "ENXIO";
1262  case EOPNOTSUPP: return "EOPNOTSUPP";
1263  case EOVERFLOW: return "EOVERFLOW";
1264  case EPERM: return "EPERM";
1265  case EPFNOSUPPORT: return "EPFNOSUPPORT";
1266  case EPIPE: return "EPIPE";
1267  case EPROTO: return "EPROTO";
1268  case EPROTONOSUPPORT: return "EPROTONOSUPPORT";
1269  case EPROTOTYPE: return "EPROTOTYPE";
1270  case ERANGE: return "ERANGE";
1271  case EREMOTE: return "EREMOTE";
1272  case EREMOTEIO: return "EREMOTEIO";
1273  case EROFS: return "EROFS";
1274  case ESHUTDOWN: return "ESHUTDOWN";
1275  case ESPIPE: return "ESPIPE";
1276  case ESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT";
1277  case ESRCH: return "ESRCH";
1278  case ESTALE: return "ESTALE";
1279  case ETIME: return "ETIME";
1280  case ETIMEDOUT: return "ETIMEDOUT";
1281  case ETXTBSY: return "ETXTBSY";
1282  case EUNATCH: return "EUNATCH";
1283  case EUSERS: return "EUSERS";
1284  /* case EWOULDBLOCK: return "EWOULDBLOCK"; */
1285  case EXDEV: return "EXDEV";
1286 
1287 #ifdef EBADE // Not available on OS X
1288  case EBADE: return "EBADE";
1289  case EBADFD: return "EBADFD";
1290  case EBADSLT: return "EBADSLT";
1291  case EDEADLOCK: return "EDEADLOCK";
1292  case EBADR: return "EBADR";
1293  case EBADRQC: return "EBADRQC";
1294  case ECHRNG: return "ECHRNG";
1295 #ifdef EISNAM // Not available on OS X, Illumos, Solaris
1296  case EISNAM: return "EISNAM";
1297  case EKEYEXPIRED: return "EKEYEXPIRED";
1298  case EKEYREJECTED: return "EKEYREJECTED";
1299  case EKEYREVOKED: return "EKEYREVOKED";
1300 #endif
1301  case EL2HLT: return "EL2HLT";
1302  case EL2NSYNC: return "EL2NSYNC";
1303  case EL3HLT: return "EL3HLT";
1304  case EL3RST: return "EL3RST";
1305  case ELIBBAD: return "ELIBBAD";
1306  case ELIBMAX: return "ELIBMAX";
1307  case ELIBSCN: return "ELIBSCN";
1308  case ELIBEXEC: return "ELIBEXEC";
1309 #ifdef ENOMEDIUM // Not available on OS X, Illumos, Solaris
1310  case ENOMEDIUM: return "ENOMEDIUM";
1311  case EMEDIUMTYPE: return "EMEDIUMTYPE";
1312 #endif
1313  case ENONET: return "ENONET";
1314  case ENOPKG: return "ENOPKG";
1315  case EREMCHG: return "EREMCHG";
1316  case ERESTART: return "ERESTART";
1317  case ESTRPIPE: return "ESTRPIPE";
1318 #ifdef EUCLEAN // Not available on OS X, Illumos, Solaris
1319  case EUCLEAN: return "EUCLEAN";
1320 #endif
1321  case EXFULL: return "EXFULL";
1322 #endif // EBADE
1323  default: return "Unknown";
1324  }
1325 }
1326 
1334 const char *
1336 {
1337  if (rc == pcmk_rc_ok) {
1338  return "OK";
1339  }
1340  if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < PCMK__N_RC)) {
1341  return pcmk__rcs[pcmk_rc_error - rc].desc;
1342  }
1343  if (rc < 0) {
1344  return "Unknown error";
1345  }
1346  return strerror(rc);
1347 }
1348 
1349 // This returns negative values for errors
1350 int
1352 {
1353  if (rc >= 0) {
1354  return -rc; // OK or system errno
1355  }
1356  if ((rc <= pcmk_rc_error) && ((pcmk_rc_error - rc) < PCMK__N_RC)) {
1357  return pcmk__rcs[pcmk_rc_error - rc].legacy_rc;
1358  }
1359  return -pcmk_err_generic;
1360 }
1361 
1362 int
1363 pcmk_legacy2rc(int legacy_rc)
1364 {
1365  legacy_rc = abs(legacy_rc);
1366  switch (legacy_rc) {
1371  case pcmk_err_old_data: return pcmk_rc_old_data;
1376  case pcmk_err_cib_save: return pcmk_rc_cib_save;
1378  case pcmk_err_multiple: return pcmk_rc_multiple;
1380  case pcmk_err_already: return pcmk_rc_already;
1383  case pcmk_err_generic: return pcmk_rc_error;
1384  case pcmk_ok: return pcmk_rc_ok;
1385  default: return legacy_rc; // system errno
1386  }
1387 }
1388 
1389 const char *
1391 {
1392  /* http://www.bzip.org/1.0.3/html/err-handling.html */
1393  switch (rc) {
1394  case BZ_OK:
1395  case BZ_RUN_OK:
1396  case BZ_FLUSH_OK:
1397  case BZ_FINISH_OK:
1398  case BZ_STREAM_END:
1399  return "Ok";
1400  case BZ_CONFIG_ERROR:
1401  return "libbz2 has been improperly compiled on your platform";
1402  case BZ_SEQUENCE_ERROR:
1403  return "library functions called in the wrong order";
1404  case BZ_PARAM_ERROR:
1405  return "parameter is out of range or otherwise incorrect";
1406  case BZ_MEM_ERROR:
1407  return "memory allocation failed";
1408  case BZ_DATA_ERROR:
1409  return "data integrity error is detected during decompression";
1410  case BZ_DATA_ERROR_MAGIC:
1411  return "the compressed stream does not start with the correct magic bytes";
1412  case BZ_IO_ERROR:
1413  return "error reading or writing in the compressed file";
1414  case BZ_UNEXPECTED_EOF:
1415  return "compressed file finishes before the logical end of stream is detected";
1416  case BZ_OUTBUFF_FULL:
1417  return "output data will not fit into the buffer provided";
1418  }
1419  return "Unknown error";
1420 }
1421 
1422 void
1423 crm_log_output_fn(const char *file, const char *function, int line, int level, const char *prefix,
1424  const char *output)
1425 {
1426  const char *next = NULL;
1427  const char *offset = NULL;
1428 
1429  if (output == NULL) {
1430  level = LOG_DEBUG;
1431  output = "-- empty --";
1432  }
1433 
1434  next = output;
1435  do {
1436  offset = next;
1437  next = strchrnul(offset, '\n');
1438  do_crm_log_alias(level, file, function, line, "%s [ %.*s ]", prefix,
1439  (int)(next - offset), offset);
1440  if (next[0] != 0) {
1441  next++;
1442  }
1443 
1444  } while (next != NULL && next[0] != 0);
1445 }
1446 
1447 char *
1448 crm_strdup_printf (char const *format, ...)
1449 {
1450  va_list ap;
1451  int len = 0;
1452  char *string = NULL;
1453 
1454  va_start(ap, format);
1455 
1456  len = vasprintf (&string, format, ap);
1457  CRM_ASSERT(len > 0);
1458 
1459  va_end(ap);
1460  return string;
1461 }
#define CRM_CORE_DIR
Definition: config.h:38
#define LOG_TRACE
Definition: logging.h:29
A dumping ground.
#define crm_notice(fmt, args...)
Definition: logging.h:276
void crm_log_preinit(const char *entity, int argc, char **argv)
Definition: logging.c:717
#define ETIME
Definition: portability.h:250
#define PCMK__N_RC
Definition: logging.c:1171
gboolean safe_str_neq(const char *a, const char *b)
Definition: strings.c:182
gboolean mainloop_add_signal(int sig, void(*dispatch)(int sig))
Definition: mainloop.c:327
void crm_enable_blackbox(int nsig)
Definition: logging.c:423
unsigned int get_crm_log_level(void)
Definition: logging.c:951
void crm_disable_blackbox(int nsig)
Definition: logging.c:429
#define ENOSTR
Definition: portability.h:258
char * crm_strdup_printf(char const *format,...)
Definition: logging.c:1448
#define pcmk_err_node_unknown
Definition: error.h:61
#define ARGS_FMT
Definition: logging.c:956
#define EKEYREJECTED
Definition: portability.h:262
#define pcmk_err_old_data
Definition: error.h:52
#define pcmk_ok
Definition: error.h:45
#define pcmk_err_schema_unchanged
Definition: error.h:58
#define EREMOTEIO
Definition: portability.h:234
void crm_xml_init(void)
Definition: xml.c:4282
char * crm_system_name
Definition: utils.c:61
gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
Definition: logging.c:602
int crm_user_lookup(const char *name, uid_t *uid, gid_t *gid)
Definition: utils.c:424
#define CRM_LOG_ASSERT(expr)
Definition: logging.h:176
void crm_write_blackbox(int nsig, struct qb_log_callsite *cs)
Definition: logging.c:435
int pcmk_rc2legacy(int rc)
Definition: logging.c:1351
#define do_crm_log_alias(level, file, function, line, fmt, args...)
Log a message as if it came from a different code location.
Definition: logging.h:222
const char * daemon_option(const char *option)
Definition: logging.c:119
uint32_t pid
Definition: internal.h:77
char * strerror(int errnum)
#define pcmk_err_already
Definition: error.h:62
const char * pcmk_rc_name(int rc)
Get a return code constant name as a string.
Definition: logging.c:1181
Wrappers for and extensions to glib mainloop.
#define FMT_MAX
Definition: logging.c:189
gboolean crm_add_logfile(const char *filename)
Definition: logging.c:224
void crm_log_args(int argc, char **argv)
Definition: logging.c:958
const char * pcmk_errorname(int rc)
Definition: logging.c:992
#define pcmk_err_diff_failed
Definition: error.h:53
char uname[MAX_NAME]
Definition: internal.h:81
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code.
Definition: logging.c:1335
#define pcmk_err_diff_resync
Definition: error.h:54
#define crm_warn(fmt, args...)
Definition: logging.h:275
gboolean crm_log_init(const char *entity, uint8_t level, gboolean daemon, gboolean to_stderr, int argc, char **argv, gboolean quiet)
Definition: logging.c:767
int daemon(int nochdir, int noclose)
#define crm_debug(fmt, args...)
Definition: logging.h:279
gboolean crm_signal(int sig, void(*dispatch)(int sig))
Definition: mainloop.c:302
time_t log_time_t
Definition: logging.c:358
unsigned int crm_log_level
Definition: logging.c:48
void crm_enable_stderr(int enable)
Definition: logging.c:921
#define pcmk_err_no_quorum
Definition: error.h:49
#define pcmk_err_schema_validation
Definition: error.h:50
#define crm_trace(fmt, args...)
Definition: logging.h:280
#define do_crm_log(level, fmt, args...)
Log a message.
Definition: logging.h:129
int setenv(const char *name, const char *value, int why)
#define CRM_BLACKBOX_DIR
Definition: config.h:29
#define pcmk_err_cib_save
Definition: error.h:57
unsigned int crm_trace_nonlog
Definition: logging.c:50
void crm_update_callsites(void)
Definition: logging.c:631
#define pcmk_err_cib_backup
Definition: error.h:56
const char * pcmk_strerror(int rc)
Definition: logging.c:1017
#define pcmk_err_generic
Definition: error.h:48
#define CRM_DAEMON_USER
Definition: config.h:47
#define ECOMM
Definition: portability.h:226
#define PCMK_ERROR_OFFSET
Definition: error.h:46
#define ENOSR
Definition: portability.h:254
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
Definition: strings.c:245
#define pcmk_err_transform_failed
Definition: error.h:51
uint32_t counter
Definition: internal.h:78
#define ENOKEY
Definition: portability.h:242
#define pcmk_err_unknown_format
Definition: error.h:69
void crm_log_output_fn(const char *file, const char *function, int line, int level, const char *prefix, const char *output)
Definition: logging.c:1423
#define ELIBACC
Definition: portability.h:230
#define EUNATCH
Definition: portability.h:238
#define pcmk_err_multiple
Definition: error.h:60
#define ENODATA
Definition: portability.h:246
#define crm_perror(level, fmt, args...)
Log a system error message.
Definition: logging.h:252
gboolean crm_log_cli_init(const char *entity)
Definition: logging.c:492
#define crm_err(fmt, args...)
Definition: logging.h:274
#define ENOTUNIQ
Definition: portability.h:222
int pcmk_legacy2rc(int legacy_rc)
Definition: logging.c:1363
#define NAME_MAX
Definition: logging.c:105
gboolean daemon_option_enabled(const char *daemon, const char *option)
Definition: logging.c:167
#define pcmk_err_cib_modified
Definition: error.h:55
#define uint32_t
Definition: stdint.in.h:158
void set_daemon_option(const char *option, const char *value)
Definition: logging.c:143
#define pcmk_err_bad_nvpair
Definition: error.h:68
#define CRM_ASSERT(expr)
Definition: error.h:20
#define uint8_t
Definition: stdint.in.h:144
char * strchrnul(const char *s, int c_in)
unsigned int set_crm_log_level(unsigned int level)
Definition: logging.c:910
gboolean crm_is_true(const char *s)
Definition: strings.c:197
bool crm_is_daemon
Definition: logging.c:51
unsigned int crm_log_priority
Definition: logging.c:47
#define safe_str_eq(a, b)
Definition: util.h:74
void crm_abort(const char *file, const char *function, int line, const char *condition, gboolean do_core, gboolean do_fork)
Definition: utils.c:647
#define pcmk_err_cib_corrupt
Definition: error.h:59
void crm_bump_log_level(int argc, char **argv)
Definition: logging.c:933
#define crm_info(fmt, args...)
Definition: logging.h:277
void crm_log_deinit(void)
Definition: logging.c:182
uint64_t flags
Definition: remote.c:156
const char * bz2_strerror(int rc)
Definition: logging.c:1390
#define int32_t
Definition: stdint.in.h:157