wslog: Check environment initialization for errors

Initialiaze the cmdarg error stream earlier.

Dumpcap also needs to know earlier if it is running in capture
child mode.
This commit is contained in:
João Valverde 2021-06-24 21:20:25 +01:00
parent c2c256f0d8
commit c6a920686c
26 changed files with 217 additions and 137 deletions

View File

@ -1581,11 +1581,10 @@ main(int argc, char *argv[])
setlocale(LC_ALL, "");
#endif
cmdarg_err_init(capinfos_cmdarg_err, capinfos_cmdarg_err_cont);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("capinfos", NULL);
cmdarg_err_init(capinfos_cmdarg_err, capinfos_cmdarg_err_cont);
ws_log_init("capinfos", vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION);

View File

@ -120,11 +120,11 @@ main(int argc, char *argv[])
setlocale(LC_ALL, "");
#endif
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("captype", NULL);
cmdarg_err_init(captype_cmdarg_err, captype_cmdarg_err_cont);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("captype", vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);

View File

@ -235,7 +235,8 @@ libwsutil.so.0 libwsutil0 #MINVER#
ws_log_full@Base 3.5.0
ws_log_get_level@Base 3.5.0
ws_log_init@Base 3.5.0
ws_log_init_with_data@Base 3.5.0
ws_log_init_with_writer@Base 3.5.0
ws_log_init_with_writer_and_data@Base 3.5.0
ws_log_level_to_string@Base 3.5.0
ws_log_msg_is_active@Base 3.5.0
ws_log_parse_args@Base 3.5.0

View File

@ -60,11 +60,11 @@ main(int argc, char **argv)
dfilter_t *df;
gchar *err_msg;
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("dftest", NULL);
cmdarg_err_init(dftest_cmdarg_err, dftest_cmdarg_err_cont);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("dftest", vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);

View File

@ -4854,11 +4854,48 @@ main(int argc, char *argv[])
#endif
GString *str;
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("dumpcap", dumpcap_log_writer);
/*
* Determine if dumpcap is being requested to run in a special
* capture_child mode by going thru the command line args to see if
* a -Z is present. (-Z is a hidden option).
*
* The primary result of running in capture_child mode is that
* all messages sent out on stderr are in a special type/len/string
* format to allow message processing by type. These messages include
* error messages if dumpcap fails to start the operation it was
* requested to do, as well as various "status" messages which are sent
* when an actual capture is in progress, and a "success" message sent
* if dumpcap was requested to perform an operation other than a
* capture.
*
* Capture_child mode would normally be requested by a parent process
* which invokes dumpcap and obtains dumpcap stderr output via a pipe
* to which dumpcap stderr has been redirected. It might also have
* another pipe to obtain dumpcap stdout output; for operations other
* than a capture, that information is formatted specially for easier
* parsing by the parent process.
*
* Capture_child mode needs to be determined immediately upon
* startup so that any messages generated by dumpcap in this mode
* (eg: during initialization) will be formatted properly.
*/
for (i=1; i<argc; i++) {
if (strcmp("-Z", argv[i]) == 0) {
capture_child = TRUE;
machine_readable = TRUE; /* request machine-readable output */
#ifdef _WIN32
/* set output pipe to binary mode, to avoid ugly text conversions */
_setmode(2, O_BINARY);
#endif
}
}
cmdarg_err_init(dumpcap_cmdarg_err, dumpcap_cmdarg_err_cont);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init_with_writer("dumpcap", dumpcap_log_writer, vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);
@ -4924,43 +4961,6 @@ main(int argc, char *argv[])
}
#endif
/*
* Determine if dumpcap is being requested to run in a special
* capture_child mode by going thru the command line args to see if
* a -Z is present. (-Z is a hidden option).
*
* The primary result of running in capture_child mode is that
* all messages sent out on stderr are in a special type/len/string
* format to allow message processing by type. These messages include
* error messages if dumpcap fails to start the operation it was
* requested to do, as well as various "status" messages which are sent
* when an actual capture is in progress, and a "success" message sent
* if dumpcap was requested to perform an operation other than a
* capture.
*
* Capture_child mode would normally be requested by a parent process
* which invokes dumpcap and obtains dumpcap stderr output via a pipe
* to which dumpcap stderr has been redirected. It might also have
* another pipe to obtain dumpcap stdout output; for operations other
* than a capture, that information is formatted specially for easier
* parsing by the parent process.
*
* Capture_child mode needs to be determined immediately upon
* startup so that any messages generated by dumpcap in this mode
* (eg: during initialization) will be formatted properly.
*/
for (i=1; i<argc; i++) {
if (strcmp("-Z", argv[i]) == 0) {
capture_child = TRUE;
machine_readable = TRUE; /* request machine-readable output */
#ifdef _WIN32
/* set output pipe to binary mode, to avoid ugly text conversions */
_setmode(2, O_BINARY);
#endif
}
}
/* Initialize the pcaps list and IDBs */
global_ld.pcaps = g_array_new(FALSE, FALSE, sizeof(capture_src *));
global_ld.pcapng_passthrough = FALSE;

View File

@ -1154,11 +1154,11 @@ main(int argc, char *argv[])
gboolean valid_seed = FALSE;
unsigned int seed = 0;
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("editcap", NULL);
cmdarg_err_init(editcap_cmdarg_err, editcap_cmdarg_err_cont);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("editcap", vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION);

View File

@ -2528,13 +2528,13 @@ int main(int argc, char *argv[]) {
char *help_url;
char *help_header = NULL;
cmdarg_err_init(androiddump_cmdarg_err, androiddump_cmdarg_err);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("androiddump", NULL);
cmdarg_err_init(androiddump_cmdarg_err, androiddump_cmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, EXIT_FAILURE);
ws_log_parse_args(&argc, argv, NULL, LOG_ARGS_NOEXIT);
/*
* Get credential information for later use.

View File

@ -536,7 +536,10 @@ int main(int argc, char *argv[])
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("ciscodump", NULL);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, NULL, LOG_ARGS_NOEXIT);
/*
* Get credential information for later use.
*/

View File

@ -492,6 +492,9 @@ int main(int argc, char *argv[])
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("dpauxmon", NULL);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, NULL, LOG_ARGS_NOEXIT);
/*
* Get credential information for later use.
*/

View File

@ -125,6 +125,9 @@ int main(int argc, char* argv[])
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("etwdump", NULL);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, NULL, LOG_ARGS_NOEXIT);
/*
* Get credential information for later use.
*/

View File

@ -151,13 +151,13 @@ int main(int argc, char *argv[])
char* help_url;
char* help_header = NULL;
cmdarg_err_init(randpktdump_cmdarg_err, randpktdump_cmdarg_err);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("randpktdump", NULL);
cmdarg_err_init(randpktdump_cmdarg_err, randpktdump_cmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, EXIT_FAILURE);
ws_log_parse_args(&argc, argv, NULL, LOG_ARGS_NOEXIT);
/*
* Get credential information for later use.

View File

@ -344,6 +344,9 @@ int main(int argc, char **argv)
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("sdjournal", NULL);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, NULL, LOG_ARGS_NOEXIT);
/*
* Get credential information for later use.
*/

View File

@ -365,6 +365,9 @@ int main(int argc, char *argv[])
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("sshdump", NULL);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, NULL, LOG_ARGS_NOEXIT);
sshdump_extcap_interface = g_path_get_basename(argv[0]);
/*

View File

@ -371,6 +371,9 @@ int main(int argc, char *argv[])
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("udpdump", NULL);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, NULL, LOG_ARGS_NOEXIT);
/*
* Get credential information for later use.
*/

View File

@ -235,11 +235,14 @@ fuzz_init(int argc _U_, char **argv)
g_setenv("WIRESHARK_DEBUG_WMEM_OVERRIDE", "simple", 0);
g_setenv("G_SLICE", "always-malloc", 0);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("fuzzshark", NULL);
cmdarg_err_init(fuzzshark_cmdarg_err, fuzzshark_cmdarg_err_cont);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("fuzzshark", vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, LOG_ARGS_NOEXIT);
/*
* Get credential information for later use, and drop privileges
* before doing anything else.

View File

@ -228,11 +228,11 @@ main(int argc, char *argv[])
idb_merge_mode mode = IDB_MERGE_MODE_MAX;
merge_progress_callback_t cb;
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("mergecap", NULL);
cmdarg_err_init(mergecap_cmdarg_err, mergecap_cmdarg_err_cont);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("mergecap", vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);

View File

@ -138,11 +138,11 @@ main(int argc, char *argv[])
{0, 0, 0, 0 }
};
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("randpkt", NULL);
cmdarg_err_init(randpkt_cmdarg_err, randpkt_cmdarg_err_cont);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("randpkt", vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION);

View File

@ -449,11 +449,11 @@ main(int argc, char *argv[])
setlocale(LC_ALL, "");
#endif
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("rawshark", NULL);
cmdarg_err_init(rawshark_cmdarg_err, rawshark_cmdarg_err_cont);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("rawshark", vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION);

View File

@ -208,11 +208,11 @@ main(int argc, char *argv[])
char *infile;
const char *outfile;
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("reordercap", NULL);
cmdarg_err_init(reordercap_cmdarg_err, reordercap_cmdarg_err_cont);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("reordercap", vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION);

View File

@ -114,11 +114,11 @@ main(int argc, char *argv[])
cfile_close_failure_message
};
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("sharkd", NULL);
cmdarg_err_init(sharkd_cmdarg_err, sharkd_cmdarg_err_cont);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("sharkd", vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, INIT_FAILED);

View File

@ -1860,13 +1860,23 @@ parse_options (int argc, char *argv[])
return EXIT_SUCCESS;
}
void
text2pcap_vcmdarg_err(const char *fmt, va_list ap)
{
vfprintf(stderr, fmt, ap);
fputc('\n', stderr);
}
int
main(int argc, char *argv[])
{
int ret = EXIT_SUCCESS;
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("text2pcap", NULL);
ws_log_init("text2pcap", text2pcap_vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, text2pcap_vcmdarg_err, 1);
#ifdef _WIN32
create_app_running_mutex();

View File

@ -350,17 +350,13 @@ main(int argc, char *argv[])
setlocale(LC_ALL, "");
#endif
g_set_prgname("tfshark");
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init(NULL);
cmdarg_err_init(tfshark_cmdarg_err, tfshark_cmdarg_err_cont);
/* Command line options are parsed too late to configure logging, do it
manually. */
if (ws_log_parse_args(&argc, argv, cmdarg_err) != 0)
return INVALID_OPTION;
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("tfshark", vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION);
#ifdef _WIN32
create_app_running_mutex();

View File

@ -775,11 +775,11 @@ main(int argc, char *argv[])
setlocale(LC_ALL, "");
#endif
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("tshark", NULL);
cmdarg_err_init(tshark_cmdarg_err, tshark_cmdarg_err_cont);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("tshark", vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, INVALID_OPTION);

View File

@ -529,8 +529,10 @@ int main(int argc, char *qt_argv[])
macos_enable_layer_backing();
#endif
cmdarg_err_init(wireshark_cmdarg_err, wireshark_cmdarg_err_cont);
/* Initialize log handler early so we can have proper logging during startup. */
ws_log_init("wireshark", console_log_writer);
ws_log_init_with_writer("wireshark", console_log_writer, vcmdarg_err);
qInstallMessageHandler(qt_log_message_handler);
@ -541,7 +543,6 @@ int main(int argc, char *qt_argv[])
#ifdef DEBUG_STARTUP_TIME
prefs.gui_console_open = console_open_always;
#endif /* DEBUG_STARTUP_TIME */
cmdarg_err_init(wireshark_cmdarg_err, wireshark_cmdarg_err_cont);
#if defined(Q_OS_MAC)
/* Disable automatic addition of tab menu entries in view menu */

View File

@ -49,6 +49,11 @@
#define DOMAIN_UNDEFED(domain) ((domain) == NULL || *(domain) == '\0')
#define DOMAIN_DEFINED(domain) (!DOMAIN_UNDEFED(domain))
#define VALID_FATAL_LEVEL(level) \
(level == LOG_LEVEL_ERROR || \
level == LOG_LEVEL_CRITICAL || \
level == LOG_LEVEL_WARNING)
/*
* Note: I didn't measure it but I assume using a string array is faster than
* a GHashTable for small number N of domains.
@ -60,6 +65,8 @@ typedef struct {
} log_filter_t;
/* If the module is not initialized by calling ws_log_init() all messages
* will be printed regardless of log level. This is a feature, not a bug. */
static enum ws_log_level current_log_level = LOG_LEVEL_NONE;
static gboolean color_enabled = FALSE;
@ -90,6 +97,10 @@ static gboolean init_complete = FALSE;
#endif
static void print_err(void (*vcmdarg_err)(const char *, va_list ap),
int exit_failure,
const char *fmt, ...);
static void ws_log_cleanup(void);
@ -254,12 +265,12 @@ enum ws_log_level ws_log_get_level(void)
}
enum ws_log_level ws_log_set_level(enum ws_log_level log_level)
void ws_log_set_level(enum ws_log_level level)
{
if (log_level > LOG_LEVEL_NONE && log_level < _LOG_LEVEL_LAST)
current_log_level = log_level;
if (level <= LOG_LEVEL_NONE || level >= _LOG_LEVEL_LAST)
return;
return current_log_level;
current_log_level = level;
}
@ -284,20 +295,20 @@ static const char *opt_debug = "--log-debug";
static const char *opt_noisy = "--log-noisy";
static void print_err(void (*log_args_print_err)(const char *, va_list ap),
int log_args_exit_failure,
static void print_err(void (*vcmdarg_err)(const char *, va_list ap),
int exit_failure,
const char *fmt, ...)
{
va_list ap;
if (log_args_print_err == NULL)
if (vcmdarg_err == NULL)
return;
va_start(ap, fmt);
log_args_print_err(fmt, ap);
vcmdarg_err(fmt, ap);
va_end(ap);
if (log_args_exit_failure >= 0)
exit(log_args_exit_failure);
if (exit_failure != LOG_ARGS_NOEXIT)
exit(exit_failure);
}
@ -312,6 +323,11 @@ int ws_log_parse_args(int *argc_ptr, char *argv[],
const char *option, *value;
int prune_extra;
if (argc_ptr == NULL || argv == NULL)
return -1;
/* Configure from command line. */
while (*ptr != NULL) {
if (g_str_has_prefix(*ptr, opt_level)) {
option = opt_level;
@ -508,21 +524,25 @@ void ws_log_set_noisy_filter(const char *str_filter)
}
enum ws_log_level ws_log_set_fatal(enum ws_log_level log_level)
void ws_log_set_fatal(enum ws_log_level level)
{
/* Not possible to set lower priority than "warning" to fatal. */
if (log_level < LOG_LEVEL_WARNING)
return LOG_LEVEL_NONE;
if (!VALID_FATAL_LEVEL(level))
return;
fatal_log_level = log_level;
return fatal_log_level;
fatal_log_level = level;
}
enum ws_log_level ws_log_set_fatal_str(const char *str_level)
{
enum ws_log_level level = string_to_log_level(str_level);
return ws_log_set_fatal(level);
enum ws_log_level level;
level = string_to_log_level(str_level);
if (!VALID_FATAL_LEVEL(level))
return LOG_LEVEL_NONE;
fatal_log_level = level;
return fatal_log_level;
}
@ -561,7 +581,8 @@ static void glib_log_handler(const char *domain, GLogLevelFlags flags,
* to communicate with the parent and it will block. Any failures are
* therefore ignored.
*/
void ws_log_init(const char *progname, ws_log_writer_cb *writer)
void ws_log_init(const char *progname,
void (*vcmdarg_err)(const char *, va_list ap))
{
const char *env;
@ -570,8 +591,7 @@ void ws_log_init(const char *progname, ws_log_writer_cb *writer)
g_set_prgname(progname);
}
if (writer)
registered_log_writer = writer;
current_log_level = DEFAULT_LOG_LEVEL;
#if GLIB_CHECK_VERSION(2,50,0)
color_enabled = g_log_writer_supports_color(fileno(stderr));
@ -584,15 +604,35 @@ void ws_log_init(const char *progname, ws_log_writer_cb *writer)
color_enabled = FALSE;
#endif
current_log_level = DEFAULT_LOG_LEVEL;
/* Set the GLib log handler for the default domain. */
g_log_set_handler(NULL, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL,
glib_log_handler, NULL);
/* Set the GLib log handler for GLib itself. */
g_log_set_handler("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL,
glib_log_handler, NULL);
atexit(ws_log_cleanup);
/* Configure from environment. */
env = g_getenv(ENV_VAR_LEVEL);
if (env != NULL)
ws_log_set_level_str(env);
if (env != NULL) {
if (ws_log_set_level_str(env) == LOG_LEVEL_NONE) {
print_err(vcmdarg_err, LOG_ARGS_NOEXIT,
"Ignoring invalid environment value %s=\"%s\"",
ENV_VAR_LEVEL, env);
}
}
env = g_getenv(ENV_VAR_FATAL);
if (env != NULL)
ws_log_set_fatal_str(env);
if (env != NULL) {
if (ws_log_set_fatal_str(env) == LOG_LEVEL_NONE) {
print_err(vcmdarg_err, LOG_ARGS_NOEXIT,
"Ignoring invalid environment value %s=\"%s\"",
ENV_VAR_FATAL, env);
}
}
env = g_getenv(ENV_VAR_DOMAINS);
if (env != NULL)
@ -606,29 +646,30 @@ void ws_log_init(const char *progname, ws_log_writer_cb *writer)
if (env != NULL)
ws_log_set_noisy_filter(env);
/* Set the GLib log handler for the default domain. */
g_log_set_handler(NULL, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL,
glib_log_handler, NULL);
/* Set the GLib log handler for GLib itself. */
g_log_set_handler("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL,
glib_log_handler, NULL);
atexit(ws_log_cleanup);
#ifndef WS_DISABLE_DEBUG
init_complete = TRUE;
#endif
}
void ws_log_init_with_data(const char *progname, ws_log_writer_cb *writer,
void ws_log_init_with_writer(const char *progname,
ws_log_writer_cb *writer,
void (*vcmdarg_err)(const char *, va_list ap))
{
registered_log_writer = writer;
ws_log_init(progname, vcmdarg_err);
}
void ws_log_init_with_writer_and_data(const char *progname,
ws_log_writer_cb *writer,
void *user_data,
ws_log_writer_free_data_cb *free_user_data)
ws_log_writer_free_data_cb *free_user_data,
void (*vcmdarg_err)(const char *, va_list ap))
{
registered_log_writer_data = user_data;
registered_log_writer_data_free = free_user_data;
ws_log_init(progname, writer);
ws_log_init_with_writer(progname, writer, vcmdarg_err);
}

View File

@ -67,7 +67,7 @@ enum ws_log_level ws_log_get_level(void);
/** Set the actice log level. Returns the same value (the active level). */
WS_DLL_PUBLIC
enum ws_log_level ws_log_set_level(enum ws_log_level log_level);
void ws_log_set_level(enum ws_log_level log_level);
/** Set the actice log level from a string.
@ -117,7 +117,7 @@ void ws_log_set_noisy_filter(const char *str_filter);
* LOG_LEVEL_ERROR is always fatal.
*/
WS_DLL_PUBLIC
enum ws_log_level ws_log_set_fatal(enum ws_log_level log_level);
void ws_log_set_fatal(enum ws_log_level log_level);
/** Set the fatal log level from a string.
@ -129,6 +129,8 @@ WS_DLL_PUBLIC
enum ws_log_level ws_log_set_fatal_str(const char *str_level);
#define LOG_ARGS_NOEXIT -1
/** Parses the command line arguments for log options.
*
* Returns zero for no error, non-zero for a bad option value.
@ -146,7 +148,8 @@ int ws_log_parse_args(int *argc_ptr, char *argv[],
* is NULL the default log writer is used.
*/
WS_DLL_PUBLIC
void ws_log_init(const char *progname, ws_log_writer_cb *writer);
void ws_log_init(const char *progname,
void (*vcmdarg_err)(const char *, va_list ap));
/** Initializes the logging code.
@ -156,9 +159,17 @@ void ws_log_init(const char *progname, ws_log_writer_cb *writer);
* is passed it will be called with user_data when the program terminates.
*/
WS_DLL_PUBLIC
void ws_log_init_with_data(const char *progname, ws_log_writer_cb *writer,
void *user_data,
ws_log_writer_free_data_cb *free_user_data);
void ws_log_init_with_writer(const char *progname,
ws_log_writer_cb *writer,
void (*vcmdarg_err)(const char *, va_list ap));
WS_DLL_PUBLIC
void ws_log_init_with_writer_and_data(const char *progname,
ws_log_writer_cb *writer,
void *user_data,
ws_log_writer_free_data_cb *free_user_data,
void (*vcmdarg_err)(const char *, va_list ap));
/** This function is called to output a message to the log.