root/lib/common/logging.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. crm_glib_handler
  2. crm_trigger_blackbox
  3. daemon_option
  4. set_daemon_option
  5. daemon_option_enabled
  6. crm_log_deinit
  7. set_format_string
  8. crm_add_logfile
  9. blackbox_logger
  10. crm_control_blackbox
  11. crm_enable_blackbox
  12. crm_disable_blackbox
  13. crm_write_blackbox
  14. crm_log_cli_init
  15. crm_quark_to_string
  16. crm_log_filter_source
  17. crm_log_filter
  18. crm_is_callsite_active
  19. crm_update_callsites
  20. crm_tracing_enabled
  21. crm_priority2int
  22. crm_identity
  23. crm_log_preinit
  24. crm_log_init
  25. set_crm_log_level
  26. crm_enable_stderr
  27. crm_bump_log_level
  28. get_crm_log_level
  29. crm_log_args
  30. pcmk_errorname
  31. pcmk_strerror
  32. bz2_strerror
  33. crm_log_output_fn
  34. crm_strdup_printf

   1 /*
   2  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
   3  *
   4  * This library is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU Lesser General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2.1 of the License, or (at your option) any later version.
   8  *
   9  * This library is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12  * Lesser General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU Lesser General Public
  15  * License along with this library; if not, write to the Free Software
  16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  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,
     /* [previous][next][first][last][top][bottom][index][help] */
  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                 /* log and record how we got here */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 108 {
 109     if(nsig == SIGTRAP) {
 110         /* Turn it on if it wasn't already */
 111         crm_enable_blackbox(nsig);
 112     }
 113     crm_write_blackbox(nsig, NULL);
 114 }
 115 
 116 const char *
 117 daemon_option(const char *option)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 190 {
 191     int offset = 0;
 192     char fmt[FMT_MAX];
 193 
 194     if (method > QB_LOG_STDERR) {
 195         /* When logging to a file */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 223 {
 224     bool is_default = false;
 225     static int default_fd = -1;
 226     static gboolean have_logfile = FALSE;
 227 
 228     /* @COMPAT This should be CRM_LOG_DIR "/pacemaker.log". We aren't changing
 229      * it yet because it will be a significant user-visible change to publicize.
 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;           /* Nothing to do */
 245     } else if(safe_str_eq(filename, "none")) {
 246         return FALSE;           /* Nothing to do */
 247     } else if(safe_str_eq(filename, "/dev/null")) {
 248         return FALSE;           /* Nothing to do */
 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;           /* Nothing to do */
 255     }
 256 
 257     /* Check the parent directory */
 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     /* Check/Set permissions if we're root */
 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                 /* Wrong group */
 295                 fix = TRUE;
 296             } else if ((st.st_mode & S_IRWXG) != (S_IRGRP | S_IWGRP)) {
 297                 /* Not read/writable by the correct group */
 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     /* Close and reopen with libqb */
 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     /* qb_log_ctl(fd, QB_LOG_CONF_FILE_SYNC, 1);  Turn on synchronous writes */
 342 
 343     /* Enable callsites */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 355 {
 356     if(cs && cs->priority < LOG_ERR) {
 357         crm_write_blackbox(SIGTRAP, cs); /* Bypass the over-dumping logic */
 358     } else {
 359         crm_write_blackbox(0, cs);
 360     }
 361 }
 362 
 363 static void
 364 crm_control_blackbox(int nsig, bool enable)
     /* [previous][next][first][last][top][bottom][index][help] */
 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); /* Any size change drops existing entries */
 378         qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);      /* Setting the size seems to disable it */
 379 
 380         /* Enable synchronous logging */
 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         /* Save to disk on abnormal termination */
 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         /* Disable synchronous logging again when the blackbox is disabled */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 415 {
 416     crm_control_blackbox(nsig, TRUE);
 417 }
 418 
 419 void
 420 crm_disable_blackbox(int nsig)
     /* [previous][next][first][last][top][bottom][index][help] */
 421 {
 422     crm_control_blackbox(nsig, FALSE);
 423 }
 424 
 425 void
 426 crm_write_blackbox(int nsig, struct qb_log_callsite *cs)
     /* [previous][next][first][last][top][bottom][index][help] */
 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             /* The graceful case - such as assertion failure or user request */
 442 
 443             if (nsig == 0 && now == last) {
 444                 /* Prevent over-dumping */
 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             /* Flush the existing contents
 464              * A size change would also work
 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             /* Do as little as possible, just try to get what we have out
 472              * We logged the filename when the blackbox was enabled
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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         /* Blackbox gets everything if enabled */
 508         qb_bit_set(cs->targets, source);
 509 
 510     } else if (source == blackbox_trigger && blackbox_trigger > 0) {
 511         /* Should this log message result in the blackbox being dumped */
 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) {       /* No tracing to syslog */
 525         if (cs->priority <= crm_log_priority && cs->priority <= crm_log_level) {
 526             qb_bit_set(cs->targets, source);
 527         }
 528         /* Log file tracing options... */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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;            /* Reset then find targets to enable */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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) 
     /* [previous][next][first][last][top][bottom][index][help] */
 679 {
 680     if(crm_system_name != NULL) {
 681         /* Nothing to do */
 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) 
     /* [previous][next][first][last][top][bottom][index][help] */
 709 {
 710     /* Configure libqb logging with nothing turned on */
 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(); /* Sets buffer allocation strategy */
 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         /* Redirect messages from glib functions to our handler */
 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         /* and for good measure... - this enum is a bit field (!) */
 734         g_log_set_always_fatal((GLogLevelFlags) 0); /*value out of range */
 735 
 736         /* Who do we log as */
 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         /* Nuke any syslog activity until it's asked for */
 744         qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
 745 
 746         /* Set format strings and disable threading
 747          * Pacemaker and threads do not mix well (due to the amount of forking)
 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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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     /* Should we log to syslog */
 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         /* Override the default setting */
 793         crm_log_level = LOG_DEBUG;
 794     }
 795 
 796     /* What lower threshold do we have for sending to syslog */
 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         /* Nuke any syslog activity */
 808         qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
 809     }
 810 
 811     /* Should we log to stderr */ 
 812     if (daemon_option_enabled(crm_system_name, "stderr")) {
 813         /* Override the default setting */
 814         to_stderr = TRUE;
 815     }
 816     crm_enable_stderr(to_stderr);
 817 
 818     /* Should we log to a file */
 819     if (safe_str_eq("none", logfile)) {
 820         /* No soup^Hlogs for you! */
 821     } else if(crm_is_daemon) {
 822         /* The daemons always get a log file, unless explicitly set to configured 'none' */
 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     /* Summary */
 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     /* Ok, now we can start logging... */
 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         /* Original meanings from signal(7)
 883          *
 884          * Signal       Value     Action   Comment
 885          * SIGTRAP        5        Core    Trace/breakpoint trap
 886          * SIGUSR1     30,10,16    Term    User-defined signal 1
 887          * SIGUSR2     31,12,17    Term    User-defined signal 2
 888          *
 889          * Our usage is as similar as possible
 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 /* returns the old value */
 900 unsigned int
 901 set_crm_log_level(unsigned int level)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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     /* Enable after potentially logging the argstring, not before */
 938     crm_enable_stderr(TRUE);
 939 }
 940 
 941 unsigned int
 942 get_crm_log_level(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 943 {
 944     return crm_log_level;
 945 }
 946 
 947 #define ARGS_FMT "Invoked: %s"
 948 void
 949 crm_log_args(int argc, char **argv)
     /* [previous][next][first][last][top][bottom][index][help] */
 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]);    /* +1 space, +1 EOS */
 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) 
     /* [previous][next][first][last][top][bottom][index][help] */
 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         /* case EDEADLK: return "EDEADLK"; */
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         /* case ENOTSUP: return "ENOTSUP"; */
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         /* case EWOULDBLOCK: return "EWOULDBLOCK"; */
1078         case EXDEV: return "EXDEV";
1079             
1080 #ifdef EBADE
1081             /* Not available on OSX */
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 /* Not available on Illumos/Solaris */
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  /* Not available on Illumos/Solaris */
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  /* Not available on Illumos/Solaris */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
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             /* The following cases will only be hit on systems for which they are non-standard */
1173             /* coverity[dead_error_condition] False positive on non-Linux */
1174         case ENOTUNIQ:
1175             return "Name not unique on network";
1176             /* coverity[dead_error_condition] False positive on non-Linux */
1177         case ECOMM:
1178             return "Communication error on send";
1179             /* coverity[dead_error_condition] False positive on non-Linux */
1180         case ELIBACC:
1181             return "Can not access a needed shared library";
1182             /* coverity[dead_error_condition] False positive on non-Linux */
1183         case EREMOTEIO:
1184             return "Remote I/O error";
1185             /* coverity[dead_error_condition] False positive on non-Linux */
1186         case EUNATCH:
1187             return "Protocol driver not attached";
1188             /* coverity[dead_error_condition] False positive on non-Linux */
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)
     /* [previous][next][first][last][top][bottom][index][help] */
1199 {
1200     /* http://www.bzip.org/1.0.3/html/err-handling.html */
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,
     /* [previous][next][first][last][top][bottom][index][help] */
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, ...)
     /* [previous][next][first][last][top][bottom][index][help] */
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 }

/* [previous][next][first][last][top][bottom][index][help] */