diff --git a/docs/README.md b/docs/README.md index c505dcd4..93805f7d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -313,7 +313,6 @@ Here is a list of build constants and their default values: |MG_MAX_HTTP_HEADERS | 40 | Maximum number of HTTP headers | |MG_HTTP_INDEX | "index.html" | Index file for HTML directory | |MG_FATFS_ROOT | "/" | FAT FS root directory | -|MG_PUTCHAR | putchar | Character output function, used by logging | NOTE: the `MG_IO_SIZE` constant also sets maximum UDP message size, see @@ -3671,6 +3670,31 @@ Usage example: mg_hexdump(c->recv.buf, c->recv.len); // Hex dump incoming data ``` +### mg\_log\_set\_fn() + +```c +void mg_log_set_fn(void (*logfunc)(unsigned char ch)); +``` + +Redirect logs to a custom function. Parameters: +- `logfunc` - a pointer to a function that logs a single character + +Usage example: redirecting logs to syslog. + +```c +static void mylog(uint8_t ch) { + static char buf[128]; + static struct mg_iobuf log = { .buf = buf, .size = sizeof(buf), .len = 0}; + log.buf[log.len++] = ch; + if (ch == '\n' || log.len >= log.size) { + syslog(LOG_INFO, "%.*s", (int) log.len, log.buf); + log.len = 0; + } +} +... +mg_log_set_fn(mylog); +``` + ## Filesystem ### struct mg\_fs diff --git a/mongoose.c b/mongoose.c index 9d472e83..b878337b 100644 --- a/mongoose.c +++ b/mongoose.c @@ -2252,10 +2252,19 @@ char *mg_json_get_str(struct mg_str json, const char *path) { +static void default_logger(unsigned char c) { + putchar(c); +} + static const char *s_spec = "2"; +static void (*s_log_func)(unsigned char) = default_logger; + +void mg_log_set_callback(void (*fn)(unsigned char)) { + s_log_func = fn; +} static void logc(unsigned char c) { - MG_PUTCHAR(c); + s_log_func(c); } static void logs(const char *buf, size_t len) { diff --git a/mongoose.h b/mongoose.h index c84803f2..cddeb2c4 100644 --- a/mongoose.h +++ b/mongoose.h @@ -576,6 +576,10 @@ int sscanf(const char *, const char *, ...); #endif +#ifndef MG_ENABLE_LOG +#define MG_ENABLE_LOG 1 +#endif + #ifndef MG_ENABLE_MIP #define MG_ENABLE_MIP 0 #endif @@ -679,10 +683,6 @@ int sscanf(const char *, const char *, ...); #endif #endif -#ifndef MG_PUTCHAR -#define MG_PUTCHAR(x) putchar(x) -#endif - @@ -740,11 +740,19 @@ void mg_log(const char *fmt, ...); bool mg_log_prefix(int ll, const char *file, int line, const char *fname); void mg_log_set(const char *spec); void mg_hexdump(const void *buf, size_t len); +void mg_log_set_fn(void (*logfunc)(unsigned char ch)); +#if MG_ENABLE_LOG #define MG_LOG(level, args) \ do { \ if (mg_log_prefix((level), __FILE__, __LINE__, __func__)) mg_log args; \ } while (0) +#else +#define MG_LOG(level, args) \ + do { \ + if (0) mg_log args; \ + } while (0) +#endif #define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args) #define MG_INFO(args) MG_LOG(MG_LL_INFO, args) diff --git a/src/config.h b/src/config.h index 1f96cbb3..28a8afe5 100644 --- a/src/config.h +++ b/src/config.h @@ -1,5 +1,9 @@ #pragma once +#ifndef MG_ENABLE_LOG +#define MG_ENABLE_LOG 1 +#endif + #ifndef MG_ENABLE_MIP #define MG_ENABLE_MIP 0 #endif @@ -102,7 +106,3 @@ #define MG_ENABLE_FILE 0 #endif #endif - -#ifndef MG_PUTCHAR -#define MG_PUTCHAR(x) putchar(x) -#endif diff --git a/src/log.c b/src/log.c index 5a5f9e12..fd3e8638 100644 --- a/src/log.c +++ b/src/log.c @@ -1,10 +1,19 @@ #include "log.h" #include "util.h" +static void default_logger(unsigned char c) { + putchar(c); +} + static const char *s_spec = "2"; +static void (*s_log_func)(unsigned char) = default_logger; + +void mg_log_set_callback(void (*fn)(unsigned char)) { + s_log_func = fn; +} static void logc(unsigned char c) { - MG_PUTCHAR(c); + s_log_func(c); } static void logs(const char *buf, size_t len) { diff --git a/src/log.h b/src/log.h index 20510147..0450ed2b 100644 --- a/src/log.h +++ b/src/log.h @@ -8,11 +8,19 @@ void mg_log(const char *fmt, ...); bool mg_log_prefix(int ll, const char *file, int line, const char *fname); void mg_log_set(const char *spec); void mg_hexdump(const void *buf, size_t len); +void mg_log_set_fn(void (*logfunc)(unsigned char ch)); +#if MG_ENABLE_LOG #define MG_LOG(level, args) \ do { \ if (mg_log_prefix((level), __FILE__, __LINE__, __func__)) mg_log args; \ } while (0) +#else +#define MG_LOG(level, args) \ + do { \ + if (0) mg_log args; \ + } while (0) +#endif #define MG_ERROR(args) MG_LOG(MG_LL_ERROR, args) #define MG_INFO(args) MG_LOG(MG_LL_INFO, args)