|
|
|
/* _XOPEN_SOURCE >= 500 for vsnprintf() */
|
|
|
|
#ifndef _XOPEN_SOURCE
|
|
|
|
#define _XOPEN_SOURCE 700
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "first.h"
|
|
|
|
|
|
|
|
#include "ck.h"
|
|
|
|
#include "log.h"
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include "sys-time.h"
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h> /* vsnprintf() */
|
|
|
|
#include <stdlib.h> /* malloc() free() */
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_SYSLOG_H
|
|
|
|
# include <syslog.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
time_t log_epoch_secs = 0;
|
|
|
|
time_t log_monotonic_secs = 0;
|
|
|
|
|
|
|
|
int log_clock_gettime_realtime (struct timespec *ts) {
|
|
|
|
#ifdef HAVE_CLOCK_GETTIME
|
|
|
|
return clock_gettime(CLOCK_REALTIME, ts);
|
|
|
|
#else
|
|
|
|
/* Mac OSX does not provide clock_gettime()
|
|
|
|
* e.g. defined(__APPLE__) && defined(__MACH__) */
|
|
|
|
struct timeval tv;
|
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
ts->tv_sec = tv.tv_sec;
|
|
|
|
ts->tv_nsec = tv.tv_usec * 1000;
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int log_clock_gettime_monotonic (struct timespec *ts) {
|
|
|
|
#ifdef HAVE_CLOCK_GETTIME
|
|
|
|
return clock_gettime(CLOCK_MONOTONIC, ts);
|
|
|
|
#else
|
|
|
|
return log_clock_gettime_realtime(ts); /*(fallback)*/
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* retry write on EINTR or when not all data was written */
|
|
|
|
ssize_t write_all(int fd, const void * const buf, size_t count) {
|
|
|
|
ssize_t written = 0;
|
|
|
|
|
|
|
|
for (ssize_t wr; count > 0; count -= wr, written += wr) {
|
|
|
|
wr = write(fd, (const char *)buf + written, count);
|
|
|
|
if (wr > 0) continue;
|
|
|
|
|
|
|
|
if (wr < 0 && errno == EINTR) { wr = 0; continue; } /* try again */
|
|
|
|
if (0 == wr) errno = EIO; /* really shouldn't happen... */
|
|
|
|
return -1; /* fail - repeating probably won't help */
|
|
|
|
}
|
|
|
|
|
|
|
|
return written;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int log_buffer_prepare(const log_error_st *errh, const char *filename, unsigned int line, buffer *b) {
|
|
|
|
static time_t tlast;
|
|
|
|
static uint32_t tlen;
|
|
|
|
static char tstr[24]; /* 20 "%F %T" incl '\0' +3 ": (" */
|
|
|
|
switch(errh->errorlog_mode) {
|
|
|
|
case ERRORLOG_PIPE:
|
|
|
|
case ERRORLOG_FILE:
|
|
|
|
case ERRORLOG_FD:
|
|
|
|
if (-1 == errh->errorlog_fd) return -1;
|
|
|
|
/* cache the generated timestamp */
|
|
|
|
if (__builtin_expect( (tlast != log_epoch_secs), 0)) {
|
|
|
|
struct tm tm;
|
|
|
|
tlast = log_epoch_secs;
|
|
|
|
tlen = (uint32_t)
|
|
|
|
strftime(tstr, sizeof(tstr), "%F %T",
|
|
|
|
localtime_r(&tlast, &tm));
|
|
|
|
tstr[ tlen] = ':';
|
|
|
|
tstr[++tlen] = ' ';
|
|
|
|
tstr[++tlen] = '(';
|
|
|
|
/*tstr[++tlen] = '\0';*//*(not necessary for our use)*/
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer_copy_string_len(b, tstr, tlen);
|
|
|
|
break;
|
|
|
|
case ERRORLOG_SYSLOG:
|
|
|
|
/* syslog is generating its own timestamps */
|
|
|
|
buffer_copy_string_len(b, CONST_STR_LEN("("));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer_append_string(b, filename);
|
|
|
|
buffer_append_string_len(b, CONST_STR_LEN("."));
|
|
|
|
buffer_append_int(b, line);
|
|
|
|
buffer_append_string_len(b, CONST_STR_LEN(") "));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void log_write(const log_error_st *errh, buffer *b) {
|
|
|
|
switch(errh->errorlog_mode) {
|
|
|
|
case ERRORLOG_PIPE:
|
|
|
|
case ERRORLOG_FILE:
|
|
|
|
case ERRORLOG_FD:
|
|
|
|
buffer_append_string_len(b, CONST_STR_LEN("\n"));
|
[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.
Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.
In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func. In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.
- check for empty strings at config time and set value to NULL if blank
string will be ignored at runtime; at runtime, simple pointer check
for NULL can be used to check for a value that has been set and is not
blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
and use buffer_is_unset() instead of buffer_is_empty(),
where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
truncate string, and use buffer_extend() to extend
Examples where buffer known not to be NULL:
- cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
(though we might set it to NULL if buffer_is_blank(cpv->v.b))
- address of buffer is arg (&foo)
(compiler optimizer detects this in most, but not all, cases)
- buffer is checked for NULL earlier in func
- buffer is accessed in same scope without a NULL check (e.g. b->ptr)
internal behavior change:
callers must not pass a NULL buffer to some funcs.
- buffer_init_buffer() requires non-null args
- buffer_copy_buffer() requires non-null args
- buffer_append_string_buffer() requires non-null args
- buffer_string_space() requires non-null arg
12 months ago
|
|
|
write_all(errh->errorlog_fd, BUF_PTR_LEN(b));
|
|
|
|
break;
|
|
|
|
case ERRORLOG_SYSLOG:
|
|
|
|
syslog(LOG_ERR, "%s", b->ptr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
log_buffer_append_encoded (buffer * const b,
|
|
|
|
const char * const s, const size_t n)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < n && ' ' <= s[i] && s[i] <= '~'; ++i) ;/*(ASCII isprint())*/
|
|
|
|
if (i == n)
|
|
|
|
buffer_append_string_len(b, s, n); /* common case; nothing to encode */
|
|
|
|
else
|
|
|
|
buffer_append_string_c_escaped(b, s, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
__attribute_format__((__printf__, 2, 0))
|
|
|
|
static void
|
|
|
|
log_buffer_vprintf (buffer * const b,
|
|
|
|
const char * const fmt, va_list ap)
|
|
|
|
{
|
|
|
|
/* NOTE: log_buffer_prepare() ensures 0 != b->used */
|
|
|
|
/*assert(0 != b->used);*//*(only because code calcs below assume this)*/
|
|
|
|
/*assert(0 != b->size);*//*(errh->b should not have 0 size here)*/
|
[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.
Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.
In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func. In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.
- check for empty strings at config time and set value to NULL if blank
string will be ignored at runtime; at runtime, simple pointer check
for NULL can be used to check for a value that has been set and is not
blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
and use buffer_is_unset() instead of buffer_is_empty(),
where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
truncate string, and use buffer_extend() to extend
Examples where buffer known not to be NULL:
- cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
(though we might set it to NULL if buffer_is_blank(cpv->v.b))
- address of buffer is arg (&foo)
(compiler optimizer detects this in most, but not all, cases)
- buffer is checked for NULL earlier in func
- buffer is accessed in same scope without a NULL check (e.g. b->ptr)
internal behavior change:
callers must not pass a NULL buffer to some funcs.
- buffer_init_buffer() requires non-null args
- buffer_copy_buffer() requires non-null args
- buffer_append_string_buffer() requires non-null args
- buffer_string_space() requires non-null arg
12 months ago
|
|
|
size_t blen = buffer_clen(b);
|
|
|
|
size_t bsp = buffer_string_space(b)+1;
|
|
|
|
char *s = b->ptr + blen;
|
|
|
|
size_t n;
|
|
|
|
|
|
|
|
va_list aptry;
|
|
|
|
va_copy(aptry, ap);
|
|
|
|
n = (size_t)vsnprintf(s, bsp, fmt, aptry);
|
|
|
|
va_end(aptry);
|
|
|
|
|
[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.
Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.
In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func. In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.
- check for empty strings at config time and set value to NULL if blank
string will be ignored at runtime; at runtime, simple pointer check
for NULL can be used to check for a value that has been set and is not
blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
and use buffer_is_unset() instead of buffer_is_empty(),
where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
truncate string, and use buffer_extend() to extend
Examples where buffer known not to be NULL:
- cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
(though we might set it to NULL if buffer_is_blank(cpv->v.b))
- address of buffer is arg (&foo)
(compiler optimizer detects this in most, but not all, cases)
- buffer is checked for NULL earlier in func
- buffer is accessed in same scope without a NULL check (e.g. b->ptr)
internal behavior change:
callers must not pass a NULL buffer to some funcs.
- buffer_init_buffer() requires non-null args
- buffer_copy_buffer() requires non-null args
- buffer_append_string_buffer() requires non-null args
- buffer_string_space() requires non-null arg
12 months ago
|
|
|
if (n < bsp)
|
|
|
|
buffer_truncate(b, blen+n); /*buffer_commit(b, n);*/
|
|
|
|
else {
|
|
|
|
s = buffer_extend(b, n);
|
|
|
|
vsnprintf(s, n+1, fmt, ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < n && ' ' <= s[i] && s[i] <= '~'; ++i) ;/*(ASCII isprint())*/
|
[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.
Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.
In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func. In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.
- check for empty strings at config time and set value to NULL if blank
string will be ignored at runtime; at runtime, simple pointer check
for NULL can be used to check for a value that has been set and is not
blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
and use buffer_is_unset() instead of buffer_is_empty(),
where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
truncate string, and use buffer_extend() to extend
Examples where buffer known not to be NULL:
- cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
(though we might set it to NULL if buffer_is_blank(cpv->v.b))
- address of buffer is arg (&foo)
(compiler optimizer detects this in most, but not all, cases)
- buffer is checked for NULL earlier in func
- buffer is accessed in same scope without a NULL check (e.g. b->ptr)
internal behavior change:
callers must not pass a NULL buffer to some funcs.
- buffer_init_buffer() requires non-null args
- buffer_copy_buffer() requires non-null args
- buffer_append_string_buffer() requires non-null args
- buffer_string_space() requires non-null arg
12 months ago
|
|
|
if (i == n) return; /* common case; nothing to encode */
|
|
|
|
|
|
|
|
/* need to encode log line
|
|
|
|
* copy original line fragment, append encoded line to buffer, free copy */
|
|
|
|
char * const src = (char *)malloc(n);
|
|
|
|
memcpy(src, s, n); /*(note: not '\0'-terminated)*/
|
[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.
Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.
In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func. In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.
- check for empty strings at config time and set value to NULL if blank
string will be ignored at runtime; at runtime, simple pointer check
for NULL can be used to check for a value that has been set and is not
blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
and use buffer_is_unset() instead of buffer_is_empty(),
where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
truncate string, and use buffer_extend() to extend
Examples where buffer known not to be NULL:
- cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
(though we might set it to NULL if buffer_is_blank(cpv->v.b))
- address of buffer is arg (&foo)
(compiler optimizer detects this in most, but not all, cases)
- buffer is checked for NULL earlier in func
- buffer is accessed in same scope without a NULL check (e.g. b->ptr)
internal behavior change:
callers must not pass a NULL buffer to some funcs.
- buffer_init_buffer() requires non-null args
- buffer_copy_buffer() requires non-null args
- buffer_append_string_buffer() requires non-null args
- buffer_string_space() requires non-null arg
12 months ago
|
|
|
buffer_truncate(b, blen);
|
|
|
|
buffer_append_string_c_escaped(b, src, n);
|
|
|
|
free(src);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
__attribute_noinline__
|
|
|
|
static void
|
|
|
|
log_error_append_strerror (buffer * const b, const int errnum)
|
|
|
|
{
|
|
|
|
char buf[1024];
|
|
|
|
errno_t rc = ck_strerror_s(buf, sizeof(buf), errnum);
|
|
|
|
if (0 == rc || rc == ERANGE)
|
|
|
|
buffer_append_str2(b, CONST_STR_LEN(": "), buf, strlen(buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
__attribute_format__((__printf__, 4, 0))
|
|
|
|
static void
|
|
|
|
log_error_va_list_impl (log_error_st * const errh,
|
|
|
|
const char * const filename,
|
|
|
|
const unsigned int line,
|
|
|
|
const char * const fmt, va_list ap,
|
|
|
|
const int perr)
|
|
|
|
{
|
|
|
|
const int errnum = errno;
|
|
|
|
buffer * const b = &errh->b;
|
|
|
|
if (-1 == log_buffer_prepare(errh, filename, line, b)) return;
|
|
|
|
log_buffer_vprintf(b, fmt, ap);
|
|
|
|
if (perr)
|
|
|
|
log_error_append_strerror(b, errnum);
|
|
|
|
log_write(errh, b);
|
|
|
|
errno = errnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
log_error(log_error_st * const errh,
|
|
|
|
const char * const filename, const unsigned int line,
|
|
|
|
const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
log_error_va_list_impl(errh, filename, line, fmt, ap, 0);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
log_perror (log_error_st * const errh,
|
|
|
|
const char * const filename, const unsigned int line,
|
|
|
|
const char * const fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
log_error_va_list_impl(errh, filename, line, fmt, ap, 1);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
log_error_multiline_buffer (log_error_st * const restrict errh,
|
|
|
|
const char * const restrict filename,
|
|
|
|
const unsigned int line,
|
|
|
|
const buffer * const restrict multiline,
|
|
|
|
const char * const restrict fmt, ...)
|
|
|
|
{
|
|
|
|
if (multiline->used < 2) return;
|
|
|
|
|
|
|
|
const int errnum = errno;
|
|
|
|
buffer * const b = &errh->b;
|
|
|
|
if (-1 == log_buffer_prepare(errh, filename, line, b)) return;
|
|
|
|
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
log_buffer_vprintf(b, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.
Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.
In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func. In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.
- check for empty strings at config time and set value to NULL if blank
string will be ignored at runtime; at runtime, simple pointer check
for NULL can be used to check for a value that has been set and is not
blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
and use buffer_is_unset() instead of buffer_is_empty(),
where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
truncate string, and use buffer_extend() to extend
Examples where buffer known not to be NULL:
- cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
(though we might set it to NULL if buffer_is_blank(cpv->v.b))
- address of buffer is arg (&foo)
(compiler optimizer detects this in most, but not all, cases)
- buffer is checked for NULL earlier in func
- buffer is accessed in same scope without a NULL check (e.g. b->ptr)
internal behavior change:
callers must not pass a NULL buffer to some funcs.
- buffer_init_buffer() requires non-null args
- buffer_copy_buffer() requires non-null args
- buffer_append_string_buffer() requires non-null args
- buffer_string_space() requires non-null arg
12 months ago
|
|
|
const size_t prefix_len = buffer_clen(b);
|
|
|
|
const char * const end = multiline->ptr + multiline->used - 2;
|
|
|
|
const char *pos = multiline->ptr-1, *current_line;
|
|
|
|
do {
|
|
|
|
pos = strchr(current_line = pos+1, '\n');
|
|
|
|
if (!pos)
|
|
|
|
pos = end;
|
[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of
hundreds, perhaps thousands, of CPU instructions, a portion of which
are on hot code paths.
Most (buffer *) used by lighttpd are not NULL, especially since buffers
were inlined into numerous larger structs such as request_st and chunk.
In the small number of instances where that is not the case, a NULL
check is often performed earlier in a function where that buffer is
later used with a buffer_* func. In the handful of cases that remained,
a NULL check was added, e.g. with r->http_host and r->conf.server_tag.
- check for empty strings at config time and set value to NULL if blank
string will be ignored at runtime; at runtime, simple pointer check
for NULL can be used to check for a value that has been set and is not
blank ("")
- use buffer_is_blank() instead of buffer_string_is_empty(),
and use buffer_is_unset() instead of buffer_is_empty(),
where buffer is known not to be NULL so that NULL check can be skipped
- use buffer_clen() instead of buffer_string_length() when buffer is
known not to be NULL (to avoid NULL check at runtime)
- use buffer_truncate() instead of buffer_string_set_length() to
truncate string, and use buffer_extend() to extend
Examples where buffer known not to be NULL:
- cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL
(though we might set it to NULL if buffer_is_blank(cpv->v.b))
- address of buffer is arg (&foo)
(compiler optimizer detects this in most, but not all, cases)
- buffer is checked for NULL earlier in func
- buffer is accessed in same scope without a NULL check (e.g. b->ptr)
internal behavior change:
callers must not pass a NULL buffer to some funcs.
- buffer_init_buffer() requires non-null args
- buffer_copy_buffer() requires non-null args
- buffer_append_string_buffer() requires non-null args
- buffer_string_space() requires non-null arg
12 months ago
|
|
|
buffer_truncate(b, prefix_len);
|
|
|
|
log_buffer_append_encoded(b, current_line, pos - current_line);
|
|
|
|
log_write(errh, b);
|
|
|
|
} while (pos < end);
|
|
|
|
|
|
|
|
errno = errnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
log_error_st *
|
|
|
|
log_error_st_init (void)
|
|
|
|
{
|
|
|
|
log_error_st *errh = calloc(1, sizeof(log_error_st));
|
|
|
|
force_assert(errh);
|
|
|
|
errh->errorlog_fd = STDERR_FILENO;
|
|
|
|
errh->errorlog_mode = ERRORLOG_FD;
|
|
|
|
return errh;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
log_error_st_free (log_error_st *errh)
|
|
|
|
{
|
|
|
|
if (NULL == errh) return;
|
|
|
|
free(errh->b.ptr);
|
|
|
|
free(errh);
|
|
|
|
}
|