PJ_DEF(void) pj_log( const char *sender, int level, const char *format, va_list marker) { pj_time_val now; pj_parsed_time ptime; char *pre; #if PJ_LOG_USE_STACK_BUFFER char log_buffer[PJ_LOG_MAX_SIZE]; #endif int saved_level, len, print_len, indent; PJ_CHECK_STACK(); if (level > pj_log_max_level) return; if (is_logging_suspended()) return; /* Temporarily disable logging for this thread. Some of PJLIB APIs that * this function calls below will recursively call the logging function * back, hence it will cause infinite recursive calls if we allow that. */ suspend_logging(&saved_level); /* Get current date/time. */ pj_gettimeofday(&now); pj_time_decode(&now, &ptime); pre = log_buffer; if (log_decor & PJ_LOG_HAS_LEVEL_TEXT) { static const char *ltexts[] = { "FATAL:", "ERROR:", " WARN:", " INFO:", "DEBUG:", "TRACE:", "DETRC:"}; pj_ansi_strcpy(pre, ltexts[level]); pre += 6; } if (log_decor & PJ_LOG_HAS_DAY_NAME) { static const char *wdays[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; pj_ansi_strcpy(pre, wdays[ptime.wday]); pre += 3; } if (log_decor & PJ_LOG_HAS_YEAR) { if (pre!=log_buffer) *pre++ = ' '; pre += pj_utoa(ptime.year, pre); } if (log_decor & PJ_LOG_HAS_MONTH) { *pre++ = '-'; pre += pj_utoa_pad(ptime.mon+1, pre, 2, '0'); } if (log_decor & PJ_LOG_HAS_DAY_OF_MON) { *pre++ = '-'; pre += pj_utoa_pad(ptime.day, pre, 2, '0'); } if (log_decor & PJ_LOG_HAS_TIME) { if (pre!=log_buffer) *pre++ = ' '; pre += pj_utoa_pad(ptime.hour, pre, 2, '0'); *pre++ = ':'; pre += pj_utoa_pad(ptime.min, pre, 2, '0'); *pre++ = ':'; pre += pj_utoa_pad(ptime.sec, pre, 2, '0'); } if (log_decor & PJ_LOG_HAS_MICRO_SEC) { *pre++ = '.'; pre += pj_utoa_pad(ptime.msec, pre, 3, '0'); } if (log_decor & PJ_LOG_HAS_SENDER) { enum { SENDER_WIDTH = PJ_LOG_SENDER_WIDTH }; pj_size_t sender_len = strlen(sender); if (pre!=log_buffer) *pre++ = ' '; if (sender_len <= SENDER_WIDTH) { while (sender_len < SENDER_WIDTH) *pre++ = ' ', ++sender_len; while (*sender) *pre++ = *sender++; } else { int i; for (i=0; i<SENDER_WIDTH; ++i) *pre++ = *sender++; } } if (log_decor & PJ_LOG_HAS_THREAD_ID) { enum { THREAD_WIDTH = PJ_LOG_THREAD_WIDTH }; const char *thread_name = pj_thread_get_name(pj_thread_this()); pj_size_t thread_len = strlen(thread_name); *pre++ = ' '; if (thread_len <= THREAD_WIDTH) { while (thread_len < THREAD_WIDTH) *pre++ = ' ', ++thread_len; while (*thread_name) *pre++ = *thread_name++; } else { int i; for (i=0; i<THREAD_WIDTH; ++i) *pre++ = *thread_name++; } } if (log_decor != 0 && log_decor != PJ_LOG_HAS_NEWLINE) *pre++ = ' '; if (log_decor & PJ_LOG_HAS_THREAD_SWC) { void *current_thread = (void*)pj_thread_this(); if (current_thread != g_last_thread) { *pre++ = '!'; g_last_thread = current_thread; } else { *pre++ = ' '; } } else if (log_decor & PJ_LOG_HAS_SPACE) { *pre++ = ' '; } #if PJ_LOG_ENABLE_INDENT if (log_decor & PJ_LOG_HAS_INDENT) { indent = log_get_indent(); if (indent > 0) { pj_memset(pre, PJ_LOG_INDENT_CHAR, indent); pre += indent; } } #endif len = (int)(pre - log_buffer); /* Print the whole message to the string log_buffer. */ print_len = pj_ansi_vsnprintf(pre, sizeof(log_buffer)-len, format, marker); if (print_len < 0) { level = 1; print_len = pj_ansi_snprintf(pre, sizeof(log_buffer)-len, "<logging error: msg too long>"); } if (print_len < 1 || print_len >= (int)(sizeof(log_buffer)-len)) { print_len = sizeof(log_buffer) - len - 1; } len = len + print_len; if (len > 0 && len < (int)sizeof(log_buffer)-2) { if (log_decor & PJ_LOG_HAS_CR) { log_buffer[len++] = '\r'; } if (log_decor & PJ_LOG_HAS_NEWLINE) { log_buffer[len++] = '\n'; } log_buffer[len] = '\0'; } else { len = sizeof(log_buffer)-1; if (log_decor & PJ_LOG_HAS_CR) { log_buffer[sizeof(log_buffer)-3] = '\r'; } if (log_decor & PJ_LOG_HAS_NEWLINE) { log_buffer[sizeof(log_buffer)-2] = '\n'; } log_buffer[sizeof(log_buffer)-1] = '\0'; } /* It should be safe to resume logging at this point. Application can * recursively call the logging function inside the callback. */ resume_logging(&saved_level); if (log_writer) (*log_writer)(level, log_buffer, len); }
static void netlink_handler(struct ev_loop *loop, struct ev_io *io, int revents) { if (rep == NULL) { if ((rep = malloc(sizeof(*rep))) == NULL) { char emsg[DEFAULT_BUF_SZ]; if (*subj) snprintf(emsg, sizeof(emsg), "auditd error halt, auid=%u pid=%d subj=%s res=failed", audit_getloginuid(), getpid(), subj); else snprintf(emsg, sizeof(emsg), "auditd error halt, auid=%u pid=%d res=failed", audit_getloginuid(), getpid()); EV_STOP (); send_audit_event(AUDIT_DAEMON_ABORT, emsg); audit_msg(LOG_ERR, "Cannot allocate audit reply, exiting"); close_down(); if (pidfile) unlink(pidfile); shutdown_dispatcher(); return; } } if (audit_get_reply(fd, &rep->reply, GET_REPLY_NONBLOCKING, 0) > 0) { switch (rep->reply.type) { /* For now dont process these */ case NLMSG_NOOP: case NLMSG_DONE: case NLMSG_ERROR: case AUDIT_GET: /* Or these */ case AUDIT_LIST_RULES: case AUDIT_FIRST_DAEMON...AUDIT_LAST_DAEMON: break; case AUDIT_SIGNAL_INFO: if (hup_info_requested) { audit_msg(LOG_DEBUG, "HUP detected, starting config manager"); if (start_config_manager(rep)) { send_audit_event( AUDIT_DAEMON_CONFIG, "auditd error getting hup info - no change," " sending auid=? pid=? subj=? res=failed"); } rep = NULL; hup_info_requested = 0; } else if (usr1_info_requested) { char usr1[MAX_AUDIT_MESSAGE_LENGTH]; if (rep->reply.len == 24) { snprintf(usr1, sizeof(usr1), "auditd sending auid=? pid=? subj=?"); } else { snprintf(usr1, sizeof(usr1), "auditd sending auid=%u pid=%d subj=%s", rep->reply.signal_info->uid, rep->reply.signal_info->pid, rep->reply.signal_info->ctx); } send_audit_event(AUDIT_DAEMON_ROTATE, usr1); usr1_info_requested = 0; } else if (usr2_info_requested) { char usr2[MAX_AUDIT_MESSAGE_LENGTH]; if (rep->reply.len == 24) { snprintf(usr2, sizeof(usr2), "auditd resuming logging, " "sending auid=? pid=? subj=? " "res=success"); } else { snprintf(usr2, sizeof(usr2), "auditd resuming logging, " "sending auid=%u pid=%d subj=%s res=success", rep->reply.signal_info->uid, rep->reply.signal_info->pid, rep->reply.signal_info->ctx); } resume_logging(); send_audit_event(AUDIT_DAEMON_RESUME, usr2); usr2_info_requested = 0; } break; default: distribute_event(rep); rep = NULL; break; } } else { if (errno == EFBIG) {