#include "time_basic.h"
#include "close_low_fd.h"
#include "memory.h"
-#include "samba_util.h" /* LIST_SEP */
+#include "util_strlist.h" /* LIST_SEP */
+#include "blocking.h"
#include "debug.h"
/* define what facility to use for syslog */
#ifdef WITH_SYSLOG
static void debug_syslog_reload(bool enabled, bool previously_enabled,
- const char *prog_name)
+ const char *prog_name, char *option)
{
if (enabled && !previously_enabled) {
#ifdef LOG_DAEMON
#ifdef HAVE_GPFS
#include "gpfswrap.h"
static void debug_gpfs_reload(bool enabled, bool previously_enabled,
- const char *prog_name)
+ const char *prog_name, char *option)
{
gpfswrap_init();
}
#endif /* HAVE_GPFS */
+#define DEBUG_RINGBUF_SIZE (1024 * 1024)
+#define DEBUG_RINGBUF_SIZE_OPT "size="
+
+static char *debug_ringbuf;
+static size_t debug_ringbuf_size;
+static size_t debug_ringbuf_ofs;
+
+/* We ensure in debug_ringbuf_log() that this is always \0 terminated */
+char *debug_get_ringbuf(void)
+{
+ return debug_ringbuf;
+}
+
+/* Return the size of the ringbuf (including a \0 terminator) */
+size_t debug_get_ringbuf_size(void)
+{
+ return debug_ringbuf_size;
+}
+
+static void debug_ringbuf_reload(bool enabled, bool previously_enabled,
+ const char *prog_name, char *option)
+{
+ bool cmp;
+ size_t optlen = strlen(DEBUG_RINGBUF_SIZE_OPT);
+
+ debug_ringbuf_size = DEBUG_RINGBUF_SIZE;
+ debug_ringbuf_ofs = 0;
+
+ SAFE_FREE(debug_ringbuf);
+
+ if (!enabled) {
+ return;
+ }
+
+ if (option != NULL) {
+ cmp = strncmp(option, DEBUG_RINGBUF_SIZE_OPT, optlen);
+ if (cmp == 0) {
+ debug_ringbuf_size = (size_t)strtoull(
+ option + optlen, NULL, 10);
+ }
+ }
+
+ debug_ringbuf = calloc(debug_ringbuf_size, sizeof(char));
+ if (debug_ringbuf == NULL) {
+ return;
+ }
+}
+
+static void debug_ringbuf_log(int msg_level,
+ const char *msg,
+ const char *msg_no_nl)
+{
+ size_t msglen = strlen(msg);
+ size_t allowed_size;
+
+ if (debug_ringbuf == NULL) {
+ return;
+ }
+
+ /* Ensure the buffer is always \0 terminated */
+ allowed_size = debug_ringbuf_size - 1;
+
+ if (msglen > allowed_size) {
+ return;
+ }
+
+ if ((debug_ringbuf_ofs + msglen) < debug_ringbuf_ofs) {
+ return;
+ }
+
+ if ((debug_ringbuf_ofs + msglen) > allowed_size) {
+ debug_ringbuf_ofs = 0;
+ }
+
+ memcpy(debug_ringbuf + debug_ringbuf_ofs, msg, msglen);
+ debug_ringbuf_ofs += msglen;
+}
+
static struct debug_backend {
const char *name;
int log_level;
int new_log_level;
- void (*reload)(bool enabled, bool prev_enabled, const char *prog_name);
+ void (*reload)(bool enabled, bool prev_enabled,
+ const char *prog_name, char *option);
void (*log)(int msg_level, const char *msg, const char *msg_no_nl);
+ char *option;
} debug_backends[] = {
{
.name = "file",
.log = debug_gpfs_log,
},
#endif
+ {
+ .name = "ringbuf",
+ .log = debug_ringbuf_log,
+ .reload = debug_ringbuf_reload,
+ },
};
static struct debug_backend *debug_find_backend(const char *name)
static void debug_backend_parse_token(char *tok)
{
char *backend_name_option, *backend_name,*backend_level, *saveptr;
+ char *backend_option;
struct debug_backend *b;
/*
return;
}
- /*
- * No backend is using the option yet.
- */
-#if 0
backend_option = strtok_r(NULL, "\0", &saveptr);
-#endif
/*
* Find and update backend
} else {
b->new_log_level = atoi(backend_level);
}
+
+ if (backend_option != NULL) {
+ b->option = strdup(backend_option);
+ if (b->option == NULL) {
+ return;
+ }
+ }
}
/*
* disabled
*/
for (i = 0; i < ARRAY_SIZE(debug_backends); i++) {
+ SAFE_FREE(debug_backends[i].option);
debug_backends[i].new_log_level = -1;
}
bool enabled = b->new_log_level > -1;
bool previously_enabled = b->log_level > -1;
- b->reload(enabled, previously_enabled, state.prog_name);
+ b->reload(enabled, previously_enabled, state.prog_name,
+ b->option);
}
b->log_level = b->new_log_level;
}
* a buffer without the newline character.
*/
len = MIN(strlen(msg), FORMAT_BUFR_SIZE - 1);
- if (msg[len - 1] == '\n') {
+ if ((len > 0) && (msg[len - 1] == '\n')) {
len--;
}
[DBGC_DNS] = "dns",
[DBGC_LDB] = "ldb",
[DBGC_TEVENT] = "tevent",
+ [DBGC_AUTH_AUDIT] = "auth_audit",
+ [DBGC_AUTH_AUDIT_JSON] = "auth_json_audit",
+ [DBGC_KERBEROS] = "kerberos",
};
/*
void gfree_debugsyms(void)
{
+ unsigned i;
+
TALLOC_FREE(classname_table);
if ( DEBUGLEVEL_CLASS != debug_class_list_initial ) {
debug_num_classes = 0;
state.initialized = false;
+
+ for (i = 0; i < ARRAY_SIZE(debug_backends); i++) {
+ SAFE_FREE(debug_backends[i].option);
+ }
}
/****************************************************************************
/***************************************************************************
Print a Debug Header.
- Input: level - Debug level of the message (not the system-wide debug
- level. )
- cls - Debuglevel class of the calling module.
- location - Pointer to a string containing the name of the file
- from which this function was called, or an empty string
- if the __FILE__ macro is not implemented.
- func - Pointer to a string containing the name of the function
- from which this function was called, or an empty string
- if the __FUNCTION__ macro is not implemented.
-
- Output: Always true. This makes it easy to fudge a call to dbghdr()
- in a macro, since the function can be called as part of a test.
- Eg: ( (level <= DEBUGLEVEL) && (dbghdr(level,"",line)) )
-
- Notes: This function takes care of setting current_msg_level.
+ Input: level - Debug level of the message (not the system-wide debug
+ level. )
+ cls - Debuglevel class of the calling module.
+ location - Pointer to a string containing the name of the file
+ from which this function was called, or an empty string
+ if the __FILE__ macro is not implemented.
+ func - Pointer to a string containing the name of the function
+ from which this function was called, or an empty string
+ if the __FUNCTION__ macro is not implemented.
+
+ Output: Always true. This makes it easy to fudge a call to dbghdr()
+ in a macro, since the function can be called as part of a test.
+ Eg: ( (level <= DEBUGLEVEL) && (dbghdr(level,"",line)) )
+
+ Notes: This function takes care of setting current_msg_level.
****************************************************************************/