diff options
Diffstat (limited to 'sysdep/unix/log.c')
-rw-r--r-- | sysdep/unix/log.c | 101 |
1 files changed, 92 insertions, 9 deletions
diff --git a/sysdep/unix/log.c b/sysdep/unix/log.c index d4c36488..92f12f1e 100644 --- a/sysdep/unix/log.c +++ b/sysdep/unix/log.c @@ -65,14 +65,43 @@ static char *class_names[] = { "BUG" }; -static void -vlog(int class, char *msg, va_list args) +#define LOG_BUFFER_SIZE 1024 +static char log_buffer[LOG_BUFFER_SIZE]; +static char *log_buffer_pos; +static int log_buffer_remains; + + +/** + * log_reset - reset the log buffer + * + * This function resets a log buffer and discards buffered + * messages. Should be used before a log message is prepared + * using logn(). + */ +void +log_reset(void) { - char buf[1024]; - struct log_config *l; + log_buffer_pos = log_buffer; + log_buffer_remains = LOG_BUFFER_SIZE; + log_buffer[0] = 0; +} - if (bvsnprintf(buf, sizeof(buf)-1, msg, args) < 0) - bsprintf(buf + sizeof(buf) - 100, " ... <too long>"); +/** + * log_commit - commit a log message + * @class: message class information (%L_DEBUG to %L_BUG, see |lib/birdlib.h|) + * + * This function writes a message prepared in the log buffer to the + * log file (as specified in the configuration). The log buffer is + * reset after that. The log message is a full line, log_commit() + * terminates it. + * + * The message class is an integer, not a first char of a string like + * in log(), so it should be written like *L_INFO. + */ +void +log_commit(int class) +{ + struct log_config *l; WALK_LIST(l, *current_log_list) { @@ -88,18 +117,51 @@ vlog(int class, char *msg, va_list args) tm_format_datetime(tbuf, &config->tf_log, now); fprintf(l->fh, "%s <%s> ", tbuf, class_names[class]); } - fputs(buf, l->fh); + fputs(log_buffer, l->fh); fputc('\n', l->fh); fflush(l->fh); } #ifdef HAVE_SYSLOG else - syslog(syslog_priorities[class], "%s", buf); + syslog(syslog_priorities[class], "%s", log_buffer); #endif } - cli_echo(class, buf); + cli_echo(class, log_buffer); + + log_reset(); } +static void +log_print(const char *msg, va_list args) +{ + int i; + + if (log_buffer_remains == 0) + return; + + i=bvsnprintf(log_buffer_pos, log_buffer_remains, msg, args); + if (i < 0) + { + bsprintf(log_buffer + LOG_BUFFER_SIZE - 100, " ... <too long>"); + log_buffer_remains = 0; + return; + } + + log_buffer_pos += i; + log_buffer_remains -= i; +} + + +static void +vlog(int class, const char *msg, va_list args) +{ + log_reset(); + log_print(msg, args); + log_commit(class); +} + + + /** * log - log a message * @msg: printf-like formatting string with message class information @@ -109,6 +171,7 @@ vlog(int class, char *msg, va_list args) * and writes it to the corresponding log file (as specified in the * configuration). Please note that the message is automatically * formatted as a full line, no need to include |\n| inside. + * It is essentially a sequence of log_reset(), logn() and log_commit(). */ void log_msg(char *msg, ...) @@ -123,6 +186,26 @@ log_msg(char *msg, ...) va_end(args); } +/** + * logn - prepare a partial message in the log buffer + * @msg: printf-like formatting string (without message class information) + * + * This function formats a message according to the format string @msg + * and adds it to the log buffer. Messages in the log buffer are + * logged when the buffer is flushed using log_commit() function. The + * message should not contain |\n|, log_commit() also terminates a + * line. + */ +void +logn(char *msg, ...) +{ + va_list args; + + va_start(args, msg); + log_print(msg, args); + va_end(args); +} + void log_rl(struct rate_limit *rl, char *msg, ...) { |