12 #include <sys/param.h> 
   13 #include <sys/types.h> 
   16 #include <sys/utsname.h> 
   31 #include <qb/qbdefs.h> 
   37 #ifdef QB_FEATURE_LOG_HIRES_TIMESTAMPS 
   38 #define TIMESTAMP_FORMAT_SPEC "%%T" 
   41 #define TIMESTAMP_FORMAT_SPEC "%%t" 
   49 static unsigned int crm_log_priority = LOG_NOTICE;
 
   50 static GLogFunc glib_log_default = NULL;
 
   52 static gboolean crm_tracing_enabled(
void);
 
   55 crm_glib_handler(
const gchar * log_domain, GLogLevelFlags 
flags, 
const gchar * message,
 
   58     int log_level = LOG_WARNING;
 
   59     GLogLevelFlags msg_level = (flags & G_LOG_LEVEL_MASK);
 
   60     static struct qb_log_callsite *glib_cs = NULL;
 
   62     if (glib_cs == NULL) {
 
   63         glib_cs = qb_log_callsite_get(__func__, __FILE__, 
"glib-handler",
 
   69         case G_LOG_LEVEL_CRITICAL:
 
   74                 crm_abort(__FILE__, __func__, __LINE__, message, TRUE, TRUE);
 
   78         case G_LOG_LEVEL_ERROR:
 
   81         case G_LOG_LEVEL_MESSAGE:
 
   82             log_level = LOG_NOTICE;
 
   84         case G_LOG_LEVEL_INFO:
 
   87         case G_LOG_LEVEL_DEBUG:
 
   88             log_level = LOG_DEBUG;
 
   91         case G_LOG_LEVEL_WARNING:
 
   92         case G_LOG_FLAG_RECURSION:
 
   93         case G_LOG_FLAG_FATAL:
 
   94         case G_LOG_LEVEL_MASK:
 
   95             log_level = LOG_WARNING;
 
   99     do_crm_log(log_level, 
"%s: %s", log_domain, message);
 
  103 #  define NAME_MAX 256 
  115 crm_trigger_blackbox(
int nsig)
 
  117     if(nsig == SIGTRAP) {
 
  127     if (glib_log_default != NULL) {
 
  128         g_log_set_default_handler(glib_log_default, NULL);
 
  135 set_format_string(
int method, 
const char *
daemon)
 
  137     if (method == QB_LOG_SYSLOG) {
 
  139         crm_extended_logging(method, QB_FALSE);
 
  140         qb_log_format_set(method, 
"%g %p: %b");
 
  148         if (method > QB_LOG_STDERR) {
 
  150             const char *nodename = 
"localhost";
 
  152             if (
uname(&res) == 0) {
 
  153                 nodename = res.nodename;
 
  157             offset += snprintf(fmt + offset, 
FMT_MAX - offset,
 
  159                                nodename, daemon, (
unsigned long) getpid());
 
  163         offset += snprintf(fmt + offset, 
FMT_MAX - offset, 
"(%%n");
 
  164         if (crm_tracing_enabled()) {
 
  166             offset += snprintf(fmt + offset, 
FMT_MAX - offset, 
"@%%f:%%l");
 
  168         offset += snprintf(fmt + offset, 
FMT_MAX - offset, 
")");
 
  171         offset += snprintf(fmt + offset, 
FMT_MAX - offset, 
" %%g\t%%p: %%b");
 
  174         qb_log_format_set(method, fmt);
 
  178 #define DEFAULT_LOG_FILE CRM_LOG_DIR "/pacemaker.log" 
  181 logfile_disabled(
const char *filename)
 
  197 chown_logfile(
const char *filename, 
int logfd)
 
  205     if (fstat(logfd, &
st) < 0) {
 
  214         crm_warn(
"Not changing '%s' ownership because user information " 
  218     if ((
st.st_gid == pcmk_gid)
 
  219         && ((
st.st_mode & S_IRWXG) == (S_IRGRP|S_IWGRP))) {
 
  222     if (fchown(logfd, pcmk_uid, pcmk_gid) < 0) {
 
  223         crm_warn(
"Couldn't change '%s' ownership to user %s gid %d: %s",
 
  231 chmod_logfile(
const char *filename, 
int logfd)
 
  233     const char *modestr = getenv(
"PCMK_logfile_mode");
 
  234     mode_t filemode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
 
  236     if (modestr != NULL) {
 
  237         long filemode_l = strtol(modestr, NULL, 8);
 
  239         if ((filemode_l != LONG_MIN) && (filemode_l != LONG_MAX)) {
 
  240             filemode = (mode_t) filemode_l;
 
  243     if ((filemode != 0) && (fchmod(logfd, filemode) < 0)) {
 
  244         crm_warn(
"Couldn't change '%s' mode to %04o: %s",
 
  245                  filename, filemode, 
strerror(errno));
 
  251 set_logfile_permissions(
const char *filename, FILE *logfile)
 
  253     if (geteuid() == 0) {
 
  254         int logfd = fileno(logfile);
 
  255         int rc = chown_logfile(filename, logfd);
 
  260         chmod_logfile(filename, logfd);
 
  267 enable_logfile(
int fd)
 
  269     qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_TRUE);
 
  271     qb_log_ctl(fd, QB_LOG_CONF_FILE_SYNC, 1); 
 
  274 #ifdef HAVE_qb_log_conf_QB_LOG_CONF_MAX_LINE_LEN 
  276     qb_log_ctl(fd, QB_LOG_CONF_MAX_LINE_LEN, 800);
 
  283 disable_logfile(
int fd)
 
  285     qb_log_ctl(fd, QB_LOG_CONF_ENABLED, QB_FALSE);
 
  289 setenv_logfile(
const char *filename)
 
  314     FILE *logfile = NULL;
 
  315     bool is_default = 
false;
 
  317     static int default_fd = -1;
 
  318     static bool have_logfile = 
false;
 
  321     if ((filename == NULL) && !have_logfile) {
 
  326     if (logfile_disabled(filename)) {
 
  332     if (is_default && (default_fd >= 0)) {
 
  337     logfile = fopen(filename, 
"a");
 
  338     if (logfile == NULL) {
 
  340         crm_warn(
"Logging to '%s' is disabled: %s " CRM_XS " uid=%u gid=%u",
 
  341                  filename, 
strerror(rc), geteuid(), getegid());
 
  345     rc = set_logfile_permissions(filename, logfile);
 
  347         crm_warn(
"Logging to '%s' is disabled: %s " CRM_XS " permissions",
 
  355     fd = qb_log_file_open(filename);
 
  357         crm_warn(
"Logging to '%s' is disabled: %s " CRM_XS " qb_log_file_open",
 
  364         setenv_logfile(filename);
 
  366     } 
else if (default_fd >= 0) {
 
  367         crm_notice(
"Switching logging to %s", filename);
 
  368         disable_logfile(default_fd);
 
  371     crm_notice(
"Additional logging available in %s", filename);
 
  377 static int blackbox_trigger = 0;
 
  378 static volatile char *blackbox_file_prefix = NULL;
 
  381 blackbox_logger(int32_t t, 
struct qb_log_callsite *cs, 
log_time_t timestamp,
 
  384     if(cs && cs->priority < LOG_ERR) {
 
  392 crm_control_blackbox(
int nsig, 
bool enable)
 
  396     if (blackbox_file_prefix == NULL) {
 
  397         pid_t 
pid = getpid();
 
  402                                                  (
unsigned long) pid);
 
  405     if (enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
 
  406         qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 5 * 1024 * 1024); 
 
  407         qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);      
 
  410         for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
 
  411             qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_TRUE);
 
  414         crm_notice(
"Initiated blackbox recorder: %s", blackbox_file_prefix);
 
  425         blackbox_trigger = qb_log_custom_open(blackbox_logger, NULL, NULL, NULL);
 
  426         qb_log_ctl(blackbox_trigger, QB_LOG_CONF_ENABLED, QB_TRUE);
 
  427         crm_trace(
"Trigger: %d is %d %d", blackbox_trigger,
 
  428                   qb_log_ctl(blackbox_trigger, QB_LOG_CONF_STATE_GET, 0), QB_LOG_STATE_ENABLED);
 
  432     } 
else if (!enable && qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0) == QB_LOG_STATE_ENABLED) {
 
  433         qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
 
  436         for (lpc = QB_LOG_BLACKBOX; lpc < QB_LOG_TARGET_MAX; lpc++) {
 
  437             qb_log_ctl(lpc, QB_LOG_CONF_FILE_SYNC, QB_FALSE);
 
  445     crm_control_blackbox(nsig, TRUE);
 
  451     crm_control_blackbox(nsig, FALSE);
 
  467     static volatile int counter = 1;
 
  468     static volatile time_t last = 0;
 
  471     time_t now = time(NULL);
 
  473     if (blackbox_file_prefix == NULL) {
 
  482             if (nsig == 0 && now == last) {
 
  487             snprintf(buffer, 
NAME_MAX, 
"%s.%d", blackbox_file_prefix, counter++);
 
  488             if (nsig == SIGTRAP) {
 
  489                 crm_notice(
"Blackbox dump requested, please see %s for contents", buffer);
 
  493                        "Problem detected at %s:%d (%s), please see %s for additional details",
 
  494                        cs->function, cs->lineno, cs->filename, buffer);
 
  496                 crm_notice(
"Problem detected, please see %s for additional details", buffer);
 
  500             qb_log_blackbox_write_to_file(buffer);
 
  505             qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
 
  506             qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
 
  514             qb_log_blackbox_write_to_file((
const char *)blackbox_file_prefix);
 
  515             qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
 
  522 crm_quark_to_string(uint32_t tag)
 
  524     const char *text = g_quark_to_string(tag);
 
  533 crm_log_filter_source(
int source, 
const char *trace_files, 
const char *trace_fns,
 
  534                       const char *trace_fmts, 
const char *trace_tags, 
const char *trace_blackbox,
 
  535                       struct qb_log_callsite *cs)
 
  537     if (qb_log_ctl(source, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
 
  541         qb_bit_set(cs->targets, source);
 
  543     } 
else if (source == blackbox_trigger && blackbox_trigger > 0) {
 
  545         if (cs->priority <= LOG_ERR) {
 
  546             qb_bit_set(cs->targets, source);
 
  548         } 
else if (trace_blackbox) {
 
  551             if (strstr(trace_blackbox, key) != NULL) {
 
  552                 qb_bit_set(cs->targets, source);
 
  557     } 
else if (source == QB_LOG_SYSLOG) {       
 
  558         if (cs->priority <= crm_log_priority && cs->priority <= 
crm_log_level) {
 
  559             qb_bit_set(cs->targets, source);
 
  563         qb_bit_set(cs->targets, source);
 
  564     } 
else if (trace_files && strstr(trace_files, cs->filename) != NULL) {
 
  565         qb_bit_set(cs->targets, source);
 
  566     } 
else if (trace_fns && strstr(trace_fns, cs->function) != NULL) {
 
  567         qb_bit_set(cs->targets, source);
 
  568     } 
else if (trace_fmts && strstr(trace_fmts, cs->format) != NULL) {
 
  569         qb_bit_set(cs->targets, source);
 
  570     } 
else if (trace_tags
 
  573         qb_bit_set(cs->targets, source);
 
  578 crm_log_filter(
struct qb_log_callsite *cs)
 
  581     static int need_init = 1;
 
  582     static const char *trace_fns = NULL;
 
  583     static const char *trace_tags = NULL;
 
  584     static const char *trace_fmts = NULL;
 
  585     static const char *trace_files = NULL;
 
  586     static const char *trace_blackbox = NULL;
 
  590         trace_fns = getenv(
"PCMK_trace_functions");
 
  591         trace_fmts = getenv(
"PCMK_trace_formats");
 
  592         trace_tags = getenv(
"PCMK_trace_tags");
 
  593         trace_files = getenv(
"PCMK_trace_files");
 
  594         trace_blackbox = getenv(
"PCMK_trace_blackbox");
 
  596         if (trace_tags != NULL) {
 
  599             const char *offset = NULL;
 
  600             const char *next = trace_tags;
 
  605                 snprintf(token, 
sizeof(token), 
"%.*s", (
int)(next - offset), offset);
 
  607                 tag = g_quark_from_string(token);
 
  608                 crm_info(
"Created GQuark %u from token '%s' in '%s'", tag, token, trace_tags);
 
  614             } 
while (next != NULL && next[0] != 0);
 
  619     for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
 
  620         crm_log_filter_source(lpc, trace_files, trace_fns, trace_fmts, trace_tags, trace_blackbox,
 
  628     gboolean refilter = FALSE;
 
  634     if (cs->priority != level) {
 
  635         cs->priority = level;
 
  639     if (cs->tags != tags) {
 
  648     if (cs->targets == 0) {
 
  657     static gboolean log = TRUE;
 
  662             (
"Enabling callsites based on priority=%d, files=%s, functions=%s, formats=%s, tags=%s",
 
  663              crm_log_level, getenv(
"PCMK_trace_files"), getenv(
"PCMK_trace_functions"),
 
  664              getenv(
"PCMK_trace_formats"), getenv(
"PCMK_trace_tags"));
 
  666     qb_log_filter_fn_set(crm_log_filter);
 
  670 crm_tracing_enabled(
void)
 
  674     } 
else if (getenv(
"PCMK_trace_files") || getenv(
"PCMK_trace_functions")
 
  675                || getenv(
"PCMK_trace_formats") || getenv(
"PCMK_trace_tags")) {
 
  682 crm_priority2int(
const char *
name)
 
  684     struct syslog_names {
 
  688     static struct syslog_names p_names[] = {
 
  689         {
"emerg", LOG_EMERG},
 
  690         {
"alert", LOG_ALERT},
 
  693         {
"warning", LOG_WARNING},
 
  694         {
"notice", LOG_NOTICE},
 
  696         {
"debug", LOG_DEBUG},
 
  701     for (lpc = 0; name != NULL && p_names[lpc].name != NULL; lpc++) {
 
  703             return p_names[lpc].priority;
 
  706     return crm_log_priority;
 
  711 crm_identity(
const char *entity, 
int argc, 
char **argv) 
 
  720     } 
else if (argc > 0 && argv != NULL) {
 
  721         char *
mutable = strdup(argv[0]);
 
  722         char *modified = basename(
mutable);
 
  724         if (strstr(modified, 
"lt-") == modified) {
 
  745     int32_t qb_facility = 0;
 
  747     static bool have_logging = FALSE;
 
  749     if(have_logging == FALSE) {
 
  755             crm_trace_nonlog = g_quark_from_static_string(
"Pacemaker non-logging tracepoint");
 
  758         umask(S_IWGRP | S_IWOTH | S_IROTH);
 
  761         glib_log_default = g_log_set_default_handler(crm_glib_handler, NULL);
 
  764         g_log_set_always_fatal((GLogLevelFlags) 0); 
 
  767         crm_identity(entity, argc, argv);
 
  769         qb_facility = qb_log_facility2int(
"local0");
 
  774         qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
 
  775 #ifdef HAVE_qb_log_conf_QB_LOG_CONF_MAX_LINE_LEN 
  777         qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_MAX_LINE_LEN, 256);
 
  783         qb_log_tags_stringify_fn_set(crm_quark_to_string);
 
  784         for (lpc = QB_LOG_SYSLOG; lpc < QB_LOG_TARGET_MAX; lpc++) {
 
  785             qb_log_ctl(lpc, QB_LOG_CONF_THREADED, QB_FALSE);
 
  786 #ifdef HAVE_qb_log_conf_QB_LOG_CONF_ELLIPSIS 
  788             qb_log_ctl(lpc, QB_LOG_CONF_ELLIPSIS, QB_TRUE);
 
  797              int argc, 
char **argv, gboolean quiet)
 
  799     const char *syslog_priority = NULL;
 
  801     const char *f_copy = facility;
 
  814     if (facility == NULL) {
 
  828         qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, qb_log_facility2int(facility));
 
  838     if (syslog_priority) {
 
  839         crm_log_priority = crm_priority2int(syslog_priority);
 
  841     qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE, 
"*",
 
  846         qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
 
  873     crm_trace(
"Quiet: %d, facility %s", quiet, f_copy);
 
  883         const char *user = getenv(
"USER");
 
  886             crm_trace(
"Not switching to corefile directory for %s", user);
 
  894         struct passwd *pwent = getpwuid(user);
 
  897             crm_perror(LOG_ERR, 
"Cannot get name for uid: %d", user);
 
  900             crm_trace(
"Don't change active directory for regular user: %s", pwent->pw_name);
 
  902         } 
else if (chdir(base) < 0) {
 
  903             crm_perror(LOG_INFO, 
"Cannot change active directory to %s", base);
 
  906             crm_info(
"Changed active directory to %s", base);
 
  911                 snprintf(path, 512, 
"%s-%lu", 
crm_system_name, (
unsigned long) getpid());
 
  914                 crm_info(
"Changed active directory to %s/%s/%s", base, pwent->pw_name, path);
 
  957     if (enable && qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0) != QB_LOG_STATE_ENABLED) {
 
  958         qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
 
  961     } 
else if (enable == FALSE) {
 
  962         qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE);
 
  978     if (qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0)
 
  979         != QB_LOG_STATE_ENABLED) {
 
 1004     static bool logged = 
false;
 
 1005     gchar *arg_string = NULL;
 
 1007     if ((argc == 0) || (argv == NULL) || logged) {
 
 1011     arg_string = g_strjoinv(
" ", argv);
 
 1020     const char *next = NULL;
 
 1021     const char *offset = NULL;
 
 1027     if (output == NULL) {
 
 1031         output = 
"-- empty --";
 
 1039                          (
int)(next - offset), offset);
 
 1044     } 
while (next != NULL && next[0] != 0);
 
 1050     crm_log_init(name, LOG_ERR, FALSE, FALSE, 0, NULL, TRUE);
 
 1052     for (
int i = 0; i < verbosity; i++) {
 
void crm_write_blackbox(int nsig, struct qb_log_callsite *callsite)
 
#define crm_notice(fmt, args...)
 
void crm_enable_stderr(int enable)
 
gboolean mainloop_add_signal(int sig, void(*dispatch)(int sig))
 
bool pcmk__strcase_any_of(const char *s,...) G_GNUC_NULL_TERMINATED
 
gboolean crm_log_init(const char *entity, uint8_t level, gboolean daemon, gboolean to_stderr, int argc, char **argv, gboolean quiet)
 
void pcmk__set_env_option(const char *option, const char *value)
Set or unset a Pacemaker environment variable option. 
 
#define CRM_LOG_ASSERT(expr)
 
int pcmk__add_logfile(const char *filename)
Add a file to be used as a Pacemaker detail log. 
 
#define do_crm_log_alias(level, file, function, line, fmt, args...)
Log a message as if it came from a different code location. 
 
int pcmk_daemon_user(uid_t *uid, gid_t *gid)
Get user and group IDs of pacemaker daemon user. 
 
unsigned int crm_trace_nonlog
 
const char * pcmk_rc_str(int rc)
Get a user-friendly description of a return code. 
 
char * strerror(int errnum)
 
const char * pcmk__env_option(const char *option)
 
Deprecated Pacemaker logging API. 
 
Wrappers for and extensions to glib mainloop. 
 
void crm_bump_log_level(int argc, char **argv)
Make logging more verbose. 
 
void crm_log_deinit(void)
 
#define crm_warn(fmt, args...)
 
int daemon(int nochdir, int noclose)
 
#define crm_debug(fmt, args...)
 
void crm_log_output_fn(const char *file, const char *function, int line, int level, const char *prefix, const char *output)
 
gboolean crm_log_cli_init(const char *entity)
 
#define crm_trace(fmt, args...)
 
#define do_crm_log(level, fmt, args...)
Log a message. 
 
int setenv(const char *name, const char *value, int why)
 
void crm_enable_blackbox(int nsig)
 
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
 
gboolean crm_add_logfile(const char *filename)
 
sighandler_t crm_signal_handler(int sig, sighandler_t dispatch)
 
#define TIMESTAMP_FORMAT_SPEC
 
int pcmk_legacy2rc(int legacy_rc)
 
void crm_log_args(int argc, char **argv)
Log the command line (once) 
 
void pcmk__cli_init_logging(const char *name, unsigned int verbosity)
 
unsigned int set_crm_log_level(unsigned int level)
 
void crm_log_preinit(const char *entity, int argc, char **argv)
 
gboolean crm_is_callsite_active(struct qb_log_callsite *cs, uint8_t level, uint32_t tags)
 
unsigned int get_crm_log_level(void)
 
unsigned int crm_log_level
 
void crm_disable_blackbox(int nsig)
 
#define crm_perror(level, fmt, args...)
Send a system error message to both the log and stderr. 
 
char * strchrnul(const char *s, int c_in)
 
void crm_abort(const char *file, const char *function, int line, const char *condition, gboolean do_core, gboolean do_fork)
 
void crm_update_callsites(void)
 
#define crm_info(fmt, args...)
 
bool pcmk__env_option_enabled(const char *daemon, const char *option)