Fix wslog parameters altering command line arguments

This commit is contained in:
Michael Mann 2025-04-28 13:30:46 +00:00
parent 019e13a850
commit 7e15165428
24 changed files with 352 additions and 403 deletions

View File

@ -51,6 +51,7 @@
#include <locale.h>
#include <ws_exit_codes.h>
#include <wsutil/clopts_common.h>
#include <wsutil/ws_getopt.h>
#include <glib.h>
@ -1466,9 +1467,13 @@ main(int argc, char *argv[])
static const struct ws_option long_options[] = {
{"help", ws_no_argument, NULL, 'h'},
{"version", ws_no_argument, NULL, 'v'},
LONGOPT_WSLOG
{0, 0, 0, 0 }
};
#define OPTSTRING "abcdehiklmnopqrstuvxyzABCDEFHIKLMNPQRST"
static const char optstring[] = OPTSTRING;
int status = 0;
/* Set the program name. */
@ -1490,7 +1495,7 @@ main(int argc, char *argv[])
ws_log_init(vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_noisy("Finished log init and parsing command line log arguments");
@ -1526,7 +1531,7 @@ main(int argc, char *argv[])
wtap_init(true);
/* Process the options */
while ((opt = ws_getopt_long(argc, argv, "abcdehiklmnopqrstuvxyzABCDEFHIKLMNPQRST", long_options, NULL)) !=-1) {
while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) !=-1) {
switch (opt) {

View File

@ -38,6 +38,8 @@
#endif
#include <wsutil/str_util.h>
#include <ws_exit_codes.h>
#include <wsutil/clopts_common.h>
#include <wsutil/wslog.h>
#include "ui/failure_message.h"
@ -66,8 +68,11 @@ main(int argc, char *argv[])
static const struct ws_option long_options[] = {
{"help", ws_no_argument, NULL, 'h'},
{"version", ws_no_argument, NULL, 'v'},
LONGOPT_WSLOG
{0, 0, 0, 0 }
};
#define OPTSTRING "hv"
static const char optstring[] = OPTSTRING;
/* Set the program name. */
g_set_prgname("captype");
@ -88,7 +93,7 @@ main(int argc, char *argv[])
ws_log_init(vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);
ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_noisy("Finished log init and parsing command line log arguments");
@ -121,7 +126,7 @@ main(int argc, char *argv[])
wtap_init(true);
/* Process the options */
while ((opt = ws_getopt_long(argc, argv, "hv", long_options, NULL)) !=-1) {
while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) !=-1) {
switch (opt) {

View File

@ -33,6 +33,7 @@
#include <wsutil/filesystem.h>
#include <wsutil/file_util.h>
#include <wsutil/privileges.h>
#include <wsutil/clopts_common.h>
#include <wsutil/wslog.h>
#include <wsutil/ws_getopt.h>
#include <wsutil/utf8_entities.h>
@ -317,6 +318,27 @@ main(int argc, char **argv)
char *text = NULL;
int exit_status = EXIT_FAILURE;
const char* optstring = "hvC:dDflsmrtV0";
static const struct ws_option long_options[] = {
{ "help", ws_no_argument, 0, 'h' },
{ "version", ws_no_argument, 0, 'v' },
{ "debug", ws_optional_argument, 0, 'd' },
{ "flex", ws_no_argument, 0, 'f' },
{ "lemon", ws_no_argument, 0, 'l' },
{ "syntax", ws_no_argument, 0, 's' },
{ "macros", ws_no_argument, 0, 'm' },
{ "timer", ws_no_argument, 0, 't' },
{ "verbose", ws_no_argument, 0, 'V' },
{ "return-vals", ws_no_argument, 0, 'r' },
{ "optimize", ws_required_argument, 0, 1000 },
{ "types", ws_no_argument, 0, 2000 },
{ "refs", ws_no_argument, 0, 3000 },
{ "file", ws_required_argument, 0, 4000 },
LONGOPT_WSLOG
{ NULL, 0, 0, 0 }
};
int opt;
/* Set the program name. */
g_set_prgname("dftest");
@ -336,7 +358,7 @@ main(int argc, char **argv)
ws_log_init(vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);
ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_noisy("Finished log init and parsing command line log arguments");
@ -359,26 +381,6 @@ main(int argc, char **argv)
ws_init_version_info("DFTest", NULL, NULL);
const char *optstring = "hvC:dDflsmrtV0";
static struct ws_option long_options[] = {
{ "help", ws_no_argument, 0, 'h' },
{ "version", ws_no_argument, 0, 'v' },
{ "debug", ws_optional_argument, 0, 'd' },
{ "flex", ws_no_argument, 0, 'f' },
{ "lemon", ws_no_argument, 0, 'l' },
{ "syntax", ws_no_argument, 0, 's' },
{ "macros", ws_no_argument, 0, 'm' },
{ "timer", ws_no_argument, 0, 't' },
{ "verbose", ws_no_argument, 0, 'V' },
{ "return-vals", ws_no_argument, 0, 'r' },
{ "optimize", ws_required_argument, 0, 1000 },
{ "types", ws_no_argument, 0, 2000 },
{ "refs", ws_no_argument, 0, 3000 },
{ "file", ws_required_argument, 0, 4000 },
{ NULL, 0, 0, 0 }
};
int opt;
for (;;) {
opt = ws_getopt_long(argc, argv, optstring, long_options, NULL);
if (opt == -1)

View File

@ -5163,6 +5163,7 @@ main(int argc, char *argv[])
{"help", ws_no_argument, NULL, 'h'},
{"version", ws_no_argument, NULL, 'v'},
LONGOPT_CAPTURE_COMMON
LONGOPT_WSLOG
{"ifname", ws_required_argument, NULL, LONGOPT_IFNAME},
{"ifdescr", ws_required_argument, NULL, LONGOPT_IFDESCR},
{"capture-comment", ws_required_argument, NULL, LONGOPT_CAPTURE_COMMENT},
@ -5173,6 +5174,23 @@ main(int argc, char *argv[])
{0, 0, 0, 0 }
};
#ifdef HAVE_PCAP_REMOTE
#define OPTSTRING_r "r"
#define OPTSTRING_u "u"
#else
#define OPTSTRING_r
#define OPTSTRING_u
#endif
#ifdef HAVE_PCAP_SETSAMPLING
#define OPTSTRING_m "m:"
#else
#define OPTSTRING_m
#endif
#define OPTSTRING OPTSTRING_CAPTURE_COMMON "C:dghk:" OPTSTRING_m "MN:nPqQ" OPTSTRING_r "St" OPTSTRING_u "vw:Z:"
static const char optstring[] = OPTSTRING;
bool arg_error = false;
#ifndef _WIN32
@ -5271,7 +5289,7 @@ main(int argc, char *argv[])
#endif
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);
ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION);
#if DEBUG_CHILD_DUMPCAP
/* Assume that if we're specially compiled with dumpcap debugging
@ -5306,22 +5324,6 @@ main(int argc, char *argv[])
ws_init_version_info("Dumpcap", gather_dumpcap_compiled_info,
gather_dumpcap_runtime_info);
#ifdef HAVE_PCAP_REMOTE
#define OPTSTRING_r "r"
#define OPTSTRING_u "u"
#else
#define OPTSTRING_r
#define OPTSTRING_u
#endif
#ifdef HAVE_PCAP_SETSAMPLING
#define OPTSTRING_m "m:"
#else
#define OPTSTRING_m
#endif
#define OPTSTRING OPTSTRING_CAPTURE_COMMON "C:dghk:" OPTSTRING_m "MN:nPqQ" OPTSTRING_r "St" OPTSTRING_u "vw:Z:"
#if defined(__APPLE__) && defined(__LP64__)
/*
* Is this Mac OS X 10.6.0, 10.6.1, 10.6.3, or 10.6.4? If so, we need
@ -5500,7 +5502,7 @@ main(int argc, char *argv[])
global_capture_opts.capture_child = capture_child;
/* Now get our args */
while ((opt = ws_getopt_long(argc, argv, OPTSTRING, long_options, NULL)) != -1) {
while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
switch (opt) {
case 'h': /* Print help and exit */
show_help_header("Capture network packets and dump them into a pcapng or pcap file.");
@ -5667,6 +5669,10 @@ main(int argc, char *argv[])
pcap_queue_packet_limit = get_positive_int(ws_optarg, "packet_limit");
break;
default:
/* wslog arguments are okay */
if (ws_log_is_wslog_arg(opt))
break;
cmdarg_err("Invalid Option: %s", argv[ws_optind-1]);
/* FALLTHROUGH */
case '?': /* Bad flag - print usage message */

View File

@ -1413,9 +1413,13 @@ main(int argc, char *argv[])
{"preserve-packet-comments", ws_no_argument, NULL, LONGOPT_PRESERVE_PACKET_COMMENTS},
{"extract-secrets", ws_no_argument, NULL, LONGOPT_EXTRACT_SECRETS},
{"compress", ws_required_argument, NULL, LONGOPT_COMPRESS},
LONGOPT_WSLOG
{0, 0, 0, 0 }
};
#define OPTSTRING "a:A:B:c:C:dD:E:F:hi:I:Lo:rR:s:S:t:T:vVw:"
static const char optstring[] = OPTSTRING;
char *p;
uint32_t snaplen = 0; /* No limit */
chop_t chop = {0, 0, 0, 0, 0, 0}; /* No chop */
@ -1458,7 +1462,7 @@ main(int argc, char *argv[])
ws_log_init(vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_noisy("Finished log init and parsing command line log arguments");
@ -1490,7 +1494,7 @@ main(int argc, char *argv[])
wtap_init(true);
/* Process the options */
while ((opt = ws_getopt_long(argc, argv, "a:A:B:c:C:dD:E:F:hi:I:Lo:rR:s:S:t:T:vVw:", long_options, NULL)) != -1) {
while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
if (opt != LONGOPT_EXTRACT_SECRETS && opt != 'V') {
edit_option_specified = true;
}

View File

@ -5913,7 +5913,41 @@ set_pref(char *pref_name, const char *value, void *private_data,
} else if (deprecated_port_pref(pref_name, value)) {
/* Handled within deprecated_port_pref() if found */
} else if (strcmp(pref_name, "console.log.level") == 0) {
/* Handled on the command line within ws_log_parse_args() */
uint32_t mask;
enum ws_log_level level;
if (!ws_basestrtou32(value, NULL, &mask, 10)) {
ws_warning("%s is not a valid decimal number for %s.", value, pref_name);
return PREFS_SET_SYNTAX_ERR;
}
/*
* The lowest priority bit in the mask defines the level.
*/
if (mask & G_LOG_LEVEL_DEBUG)
level = LOG_LEVEL_DEBUG;
else if (mask & G_LOG_LEVEL_INFO)
level = LOG_LEVEL_INFO;
else if (mask & G_LOG_LEVEL_MESSAGE)
level = LOG_LEVEL_MESSAGE;
else if (mask & G_LOG_LEVEL_WARNING)
level = LOG_LEVEL_WARNING;
else if (mask & G_LOG_LEVEL_CRITICAL)
level = LOG_LEVEL_CRITICAL;
else if (mask & G_LOG_LEVEL_ERROR)
level = LOG_LEVEL_ERROR;
else
level = LOG_LEVEL_NONE;
if (level == LOG_LEVEL_NONE) {
/* Some values (like zero) might not contain any meaningful bits.
* Throwing an error in that case seems appropriate. */
ws_warning("Value %s is not a valid log mask for %s.", value, pref_name);
return PREFS_SET_SYNTAX_ERR;
}
ws_log_set_level(level);
return PREFS_SET_OK;
} else {
/* Handle deprecated "global" options that don't have a module

View File

@ -25,6 +25,8 @@
#include <ui/failure_message.h>
#include <wsutil/filesystem.h>
#include <wsutil/privileges.h>
#include <wsutil/clopts_common.h>
#include <wsutil/ws_getopt.h>
#include <wsutil/wslog.h>
#include <wsutil/version_info.h>
@ -129,7 +131,7 @@ fuzz_prefs_apply(void)
}
static int
fuzz_init(int argc _U_, char **argv)
fuzz_init(int argc, char **argv)
{
char *configuration_init_error;
@ -138,6 +140,10 @@ fuzz_init(int argc _U_, char **argv)
e_prefs *prefs_p;
int ret = EXIT_SUCCESS;
size_t i;
static const struct ws_option long_options[] = {
LONGOPT_WSLOG
{0, 0, 0, 0 }
};
const char *fuzz_target =
#if defined(FUZZ_DISSECTOR_TARGET)
@ -218,7 +224,7 @@ fuzz_init(int argc _U_, char **argv)
ws_log_init(vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, LOG_ARGS_NOEXIT);
ws_log_parse_args(&argc, argv, "v", long_options, vcmdarg_err, LOG_ARGS_NOEXIT);
ws_noisy("Finished log init and parsing command line log arguments");

View File

@ -32,6 +32,7 @@
#include <wsutil/strnatcmp.h>
#include <wsutil/ws_assert.h>
#include <wsutil/wslog.h>
#include <ws_exit_codes.h>
#include <cli_main.h>
#include <wsutil/version_info.h>
@ -186,8 +187,11 @@ main(int argc, char *argv[])
{"help", ws_no_argument, NULL, 'h'},
{"version", ws_no_argument, NULL, 'v'},
{"compress", ws_required_argument, NULL, LONGOPT_COMPRESS},
LONGOPT_WSLOG
{0, 0, 0, 0 }
};
#define OPTSTRING "aF:hI:s:vVw:"
static const char optstring[] = OPTSTRING;
bool do_append = false;
bool verbose = false;
int in_file_count = 0;
@ -208,7 +212,7 @@ main(int argc, char *argv[])
ws_log_init(vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, 1);
ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_noisy("Finished log init and parsing command line log arguments");
@ -241,7 +245,7 @@ main(int argc, char *argv[])
wtap_init(true);
/* Process the options first */
while ((opt = ws_getopt_long(argc, argv, "aF:hI:s:vVw:", long_options, NULL)) != -1) {
while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
switch (opt) {
case 'a':

View File

@ -116,8 +116,11 @@ main(int argc, char *argv[])
static const struct ws_option long_options[] = {
{"help", ws_no_argument, NULL, 'h'},
{"version", ws_no_argument, NULL, 'v'},
LONGOPT_WSLOG
{0, 0, 0, 0 }
};
#define OPTSTRING "b:c:F:ht:rv"
static const char optstring[] = OPTSTRING;
/* Set the program name. */
g_set_prgname("randpkt");
@ -128,7 +131,7 @@ main(int argc, char *argv[])
ws_log_init(vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_noisy("Finished log init and parsing command line log arguments");
@ -159,7 +162,7 @@ main(int argc, char *argv[])
ws_init_version_info("Randpkt", NULL, NULL);
while ((opt = ws_getopt_long(argc, argv, "b:c:F:ht:rv", long_options, NULL)) != -1) {
while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
switch (opt) {
case 'b': /* max bytes */
produce_max_bytes = get_positive_int(ws_optarg, "max bytes");

View File

@ -421,6 +421,7 @@ main(int argc, char *argv[])
{"version", ws_no_argument, NULL, 'v'},
LONGOPT_DISSECT_COMMON
LONGOPT_READ_CAPTURE_COMMON
LONGOPT_WSLOG
{0, 0, 0, 0 }
};
@ -447,7 +448,7 @@ main(int argc, char *argv[])
ws_log_init(vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_noisy("Finished log init and parsing command line log arguments");

View File

@ -33,6 +33,7 @@
#include <wsutil/plugins.h>
#endif
#include <wsutil/clopts_common.h>
#include <wsutil/wslog.h>
#include "ui/failure_message.h"
@ -156,8 +157,11 @@ main(int argc, char *argv[])
static const struct ws_option long_options[] = {
{"help", ws_no_argument, NULL, 'h'},
{"version", ws_no_argument, NULL, 'v'},
LONGOPT_WSLOG
{0, 0, 0, 0 }
};
#define OPTSTRING "hnv"
static const char optstring[] = OPTSTRING;
int file_count;
char *infile;
const char *outfile;
@ -171,7 +175,7 @@ main(int argc, char *argv[])
ws_log_init(vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_noisy("Finished log init and parsing command line log arguments");
@ -200,7 +204,7 @@ main(int argc, char *argv[])
wtap_init(true);
/* Process the options first */
while ((opt = ws_getopt_long(argc, argv, "hnv", long_options, NULL)) != -1) {
while ((opt = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
switch (opt) {
case 'n':
write_output_regardless = false;

View File

@ -71,6 +71,49 @@ capture_file cfile;
static uint32_t cum_bytes;
static frame_data ref_frame;
/*
* The leading + ensures that getopt_long() does not permute the argv[]
* entries.
*
* We have to make sure that the first getopt_long() preserves the content
* of argv[] for the subsequent getopt_long() call.
*
* We use getopt_long() in both cases to ensure that we're using a routine
* whose permutation behavior we can control in the same fashion on all
* platforms, and so that, if we ever need to process a long argument before
* doing further initialization, we can do so.
*
* Glibc and Solaris libc document that a leading + disables permutation
* of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
* and macOS don't document it, but do so anyway.
*
* We do *not* use a leading - because the behavior of a leading - is
* platform-dependent.
*/
static const struct ws_option long_options[] = {
{"api", ws_required_argument, NULL, 'a'},
{"foreground", ws_no_argument, NULL, LONGOPT_FOREGROUND},
{"help", ws_no_argument, NULL, 'h'},
{"version", ws_no_argument, NULL, 'v'},
{"config-profile", ws_required_argument, NULL, 'C'},
LONGOPT_WSLOG
{0, 0, 0, 0 }
};
const struct ws_option* sharkd_long_options(void)
{
return long_options;
}
const char* sharkd_optstring(void)
{
#define OPTSTRING "+" "a:hmvC:"
static const char optstring[] = OPTSTRING;
return optstring;
}
static void
print_current_user(void)
{
@ -108,7 +151,7 @@ main(int argc, char *argv[])
ws_log_init(vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, SHARKD_INIT_FAILED);
ws_log_parse_args(&argc, argv, sharkd_optstring(), sharkd_long_options(), vcmdarg_err, SHARKD_INIT_FAILED);
ws_noisy("Finished log init and parsing command line log arguments");

View File

@ -28,6 +28,8 @@
typedef void (*sharkd_dissect_func_t)(epan_dissect_t *edt, proto_tree *tree, struct epan_column_info *cinfo, const GSList *data_src, void *data);
#define LONGOPT_FOREGROUND 4000
/* sharkd.c */
cf_status_t sharkd_cf_open(const char *fname, unsigned int type, bool is_tempfile, int *err);
int sharkd_load_cap_file(void);
@ -49,6 +51,9 @@ wtap_block_t sharkd_get_modified_block(const frame_data *fd);
wtap_block_t sharkd_get_packet_block(const frame_data *fd);
int sharkd_set_modified_block(frame_data *fd, wtap_block_t new_block);
const char *sharkd_version(void);
const struct ws_option* sharkd_long_options(void);
const char* sharkd_optstring(void);
/* sharkd_daemon.c */
int sharkd_init(int argc, char **argv);

View File

@ -241,40 +241,6 @@ print_usage(FILE* output)
int
sharkd_init(int argc, char **argv)
{
/*
* The leading + ensures that getopt_long() does not permute the argv[]
* entries.
*
* We have to make sure that the first getopt_long() preserves the content
* of argv[] for the subsequent getopt_long() call.
*
* We use getopt_long() in both cases to ensure that we're using a routine
* whose permutation behavior we can control in the same fashion on all
* platforms, and so that, if we ever need to process a long argument before
* doing further initialization, we can do so.
*
* Glibc and Solaris libc document that a leading + disables permutation
* of options, regardless of whether POSIXLY_CORRECT is set or not; *BSD
* and macOS don't document it, but do so anyway.
*
* We do *not* use a leading - because the behavior of a leading - is
* platform-dependent.
*/
#define OPTSTRING "+" "a:hmvC:"
#define LONGOPT_FOREGROUND 4000
static const char optstring[] = OPTSTRING;
static const struct ws_option long_options[] = {
{"api", ws_required_argument, NULL, 'a'},
{"foreground", ws_no_argument, NULL, LONGOPT_FOREGROUND},
{"help", ws_no_argument, NULL, 'h'},
{"version", ws_no_argument, NULL, 'v'},
{"config-profile", ws_required_argument, NULL, 'C'},
{0, 0, 0, 0 }
};
int opt;
#ifndef _WIN32
@ -333,7 +299,7 @@ sharkd_init(int argc, char **argv)
if (ws_optind > (argc - 1))
break;
opt = ws_getopt_long(argc, argv, optstring, long_options, NULL);
opt = ws_getopt_long(argc, argv, sharkd_optstring(), sharkd_long_options(), NULL);
switch (opt) {
case 'C': /* Configuration Profile */

View File

@ -378,6 +378,18 @@ cleanup_dump_params(wtap_dump_params *params)
wtap_dump_params_cleanup(params);
}
static const struct ws_option long_options[] = {
{"help", ws_no_argument, NULL, 'h'},
{"version", ws_no_argument, NULL, 'v'},
{"compress", ws_required_argument, NULL, LONGOPT_COMPRESS},
{"little-endian", ws_no_argument, NULL, LONGOPT_LITTLE_ENDIAN},
LONGOPT_WSLOG
{0, 0, 0, 0 }
};
#define OPTSTRING "hqab:De:E:F:i:l:m:nN:o:u:P:r:s:S:t:T:v4:6:"
static const char optstring[] = OPTSTRING;
/*----------------------------------------------------------------------
* Parse CLI options
*/
@ -387,13 +399,6 @@ parse_options(int argc, char *argv[], text_import_info_t * const info, wtap_dump
int ret;
int c;
char *p;
static const struct ws_option long_options[] = {
{"help", ws_no_argument, NULL, 'h'},
{"version", ws_no_argument, NULL, 'v'},
{"compress", ws_required_argument, NULL, LONGOPT_COMPRESS},
{"little-endian", ws_no_argument, NULL, LONGOPT_LITTLE_ENDIAN},
{0, 0, 0, 0 }
};
const char *interface_name = NULL;
/* Link-layer type; see https://www.tcpdump.org/linktypes.html for details */
uint32_t pcap_link_type = 1; /* Default is LINKTYPE_ETHERNET */
@ -414,7 +419,7 @@ parse_options(int argc, char *argv[], text_import_info_t * const info, wtap_dump
ws_init_version_info("Text2pcap", NULL, NULL);
/* Scan CLI parameters */
while ((c = ws_getopt_long(argc, argv, "hqab:De:E:F:i:l:m:nN:o:u:P:r:s:S:t:T:v4:6:", long_options, NULL)) != -1) {
while ((c = ws_getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
switch (c) {
case 'h':
show_help_header("Generate a capture file from an ASCII hexdump of packets.");
@ -1050,7 +1055,7 @@ main(int argc, char *argv[])
ws_log_init(vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_noisy("Finished log init and parsing command line log arguments");

View File

@ -263,6 +263,7 @@ main(int argc, char *argv[])
static const struct ws_option long_options[] = {
{"help", ws_no_argument, NULL, 'h'},
{"version", ws_no_argument, NULL, 'v'},
LONGOPT_WSLOG
{0, 0, 0, 0 }
};
bool arg_error = false;
@ -322,7 +323,7 @@ main(int argc, char *argv[])
ws_log_init(vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_noisy("Finished log init and parsing command line log arguments");

View File

@ -1048,6 +1048,7 @@ main(int argc, char *argv[])
LONGOPT_CAPTURE_COMMON
LONGOPT_DISSECT_COMMON
LONGOPT_READ_CAPTURE_COMMON
LONGOPT_WSLOG
{"print", ws_no_argument, NULL, 'P'},
{"export-objects", ws_required_argument, NULL, LONGOPT_EXPORT_OBJECTS},
{"export-tls-session-keys", ws_required_argument, NULL, LONGOPT_EXPORT_TLS_SESSION_KEYS},
@ -1142,7 +1143,7 @@ main(int argc, char *argv[])
ws_log_init(vcmdarg_err);
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_log_parse_args(&argc, argv, optstring, long_options, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_noisy("Finished log init and parsing command line log arguments");
ws_debug("tshark started with %d args", argc);

View File

@ -235,10 +235,22 @@ static const struct ws_option long_options[] = {
LONGOPT_CAPTURE_COMMON
LONGOPT_DISSECT_COMMON
LONGOPT_READ_CAPTURE_COMMON
LONGOPT_WSLOG
{0, 0, 0, 0 }
};
static const char optstring[] = OPTSTRING;
const struct ws_option* commandline_long_options(void)
{
return long_options;
}
const char* commandline_optstring(void)
{
return optstring;
}
#ifndef HAVE_LIBPCAP
static void print_no_capture_support_error(void)
{

View File

@ -48,6 +48,10 @@ typedef struct commandline_param_info
} commandline_param_info_t;
extern const struct ws_option* commandline_long_options(void);
extern const char* commandline_optstring(void);
extern void commandline_override_prefs(int argc, char *argv[], bool opt_reset);
extern void commandline_other_options(int argc, char *argv[], bool opt_reset);

View File

@ -576,7 +576,7 @@ int main(int argc, char *qt_argv[])
#endif /* _WIN32 */
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_log_parse_args(&argc, argv, commandline_optstring(), commandline_long_options(), vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_noisy("Finished log init and parsing command line log arguments");
/*

View File

@ -547,7 +547,7 @@ int main(int argc, char *qt_argv[])
#endif /* _WIN32 */
/* Early logging command-line initialization. */
ws_log_parse_args(&argc, argv, vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_log_parse_args(&argc, argv, commandline_optstring(), commandline_long_options(), vcmdarg_err, WS_EXIT_INVALID_OPTION);
ws_noisy("Finished log init and parsing command line log arguments");
/*

View File

@ -153,7 +153,7 @@ struct epb {
};
#define ENHANCED_PACKET_BLOCK_TYPE 0x00000006
struct ws_option {
struct ws_option_tlv {
uint16_t type;
uint16_t value_length;
};
@ -501,7 +501,7 @@ pcapng_count_string_option(const char *option_value)
{
if ((option_value != NULL) && (strlen(option_value) > 0) && (strlen(option_value) < UINT16_MAX)) {
/* There's a value to write; get its length */
return (uint32_t)(sizeof(struct ws_option) +
return (uint32_t)(sizeof(struct ws_option_tlv) +
(uint16_t)ADD_PADDING(strlen(option_value)));
}
return 0; /* nothing to write */
@ -513,7 +513,7 @@ pcapng_write_string_option(pcapio_writer* pfile,
uint64_t *bytes_written, int *err)
{
size_t option_value_length;
struct ws_option option;
struct ws_option_tlv option;
const uint32_t padding = 0;
if (option_value == NULL)
@ -524,7 +524,7 @@ pcapng_write_string_option(pcapio_writer* pfile,
option.type = option_type;
option.value_length = (uint16_t)option_value_length;
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option_tlv), bytes_written, err))
return false;
if (!write_to_file(pfile, (const uint8_t*)option_value, (int) option_value_length, bytes_written, err))
@ -579,7 +579,7 @@ pcapng_write_section_header_block(pcapio_writer* pfile,
int *err)
{
struct shb shb;
struct ws_option option;
struct ws_option_tlv option;
uint32_t block_total_length;
uint32_t options_length;
@ -596,7 +596,7 @@ pcapng_write_section_header_block(pcapio_writer* pfile,
options_length += pcapng_count_string_option(appname);
/* If we have options add size of end-of-options */
if (options_length != 0) {
options_length += (uint32_t)sizeof(struct ws_option);
options_length += (uint32_t)sizeof(struct ws_option_tlv);
}
block_total_length += options_length;
@ -632,7 +632,7 @@ pcapng_write_section_header_block(pcapio_writer* pfile,
/* write end of options */
option.type = OPT_ENDOFOPT;
option.value_length = 0;
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option_tlv), bytes_written, err))
return false;
}
@ -656,7 +656,7 @@ pcapng_write_interface_description_block(pcapio_writer* pfile,
int *err)
{
struct idb idb;
struct ws_option option;
struct ws_option_tlv option;
uint32_t block_total_length;
uint32_t options_length;
const uint32_t padding = 0;
@ -674,20 +674,20 @@ pcapng_write_interface_description_block(pcapio_writer* pfile,
/* 08 - IDB_IF_SPEED */
if (if_speed != 0) {
options_length += (uint32_t)(sizeof(struct ws_option) +
options_length += (uint32_t)(sizeof(struct ws_option_tlv) +
sizeof(uint64_t));
}
/* 09 - IDB_TSRESOL */
if (tsresol != 0) {
options_length += (uint32_t)(sizeof(struct ws_option) +
sizeof(struct ws_option));
options_length += (uint32_t)(sizeof(struct ws_option_tlv) +
sizeof(struct ws_option_tlv));
}
/* 11 - IDB_FILTER */
if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < UINT16_MAX - 1)) {
/* No, this isn't a string, it has an extra type byte */
options_length += (uint32_t)(sizeof(struct ws_option) +
options_length += (uint32_t)(sizeof(struct ws_option_tlv) +
(uint16_t)(ADD_PADDING(strlen(filter)+ 1)));
}
@ -699,7 +699,7 @@ pcapng_write_interface_description_block(pcapio_writer* pfile,
/* If we have options add size of end-of-options */
if (options_length != 0) {
options_length += (uint32_t)sizeof(struct ws_option);
options_length += (uint32_t)sizeof(struct ws_option_tlv);
}
block_total_length += options_length;
@ -733,7 +733,7 @@ pcapng_write_interface_description_block(pcapio_writer* pfile,
option.type = IDB_IF_SPEED;
option.value_length = sizeof(uint64_t);
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option_tlv), bytes_written, err))
return false;
if (!write_to_file(pfile, (const uint8_t*)&if_speed, sizeof(uint64_t), bytes_written, err))
@ -745,7 +745,7 @@ pcapng_write_interface_description_block(pcapio_writer* pfile,
option.type = IDB_TSRESOL;
option.value_length = sizeof(uint8_t);
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option_tlv), bytes_written, err))
return false;
if (!write_to_file(pfile, (const uint8_t*)&tsresol, sizeof(uint8_t), bytes_written, err))
@ -762,7 +762,7 @@ pcapng_write_interface_description_block(pcapio_writer* pfile,
if ((filter != NULL) && (strlen(filter) > 0) && (strlen(filter) < UINT16_MAX - 1)) {
option.type = IDB_FILTER;
option.value_length = (uint16_t)(strlen(filter) + 1 );
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option_tlv), bytes_written, err))
return false;
/* The first byte of the Option Data keeps a code of the filter used, 0 = lipbpcap filter string */
@ -790,7 +790,7 @@ pcapng_write_interface_description_block(pcapio_writer* pfile,
/* write end of options */
option.type = OPT_ENDOFOPT;
option.value_length = 0;
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option_tlv), bytes_written, err))
return false;
}
@ -813,7 +813,7 @@ pcapng_write_enhanced_packet_block(pcapio_writer* pfile,
int *err)
{
struct epb epb;
struct ws_option option;
struct ws_option_tlv option;
uint32_t block_total_length;
uint64_t timestamp;
uint32_t options_length;
@ -828,12 +828,12 @@ pcapng_write_enhanced_packet_block(pcapio_writer* pfile,
options_length = 0;
options_length += pcapng_count_string_option(comment);
if (flags != 0) {
options_length += (uint32_t)(sizeof(struct ws_option) +
options_length += (uint32_t)(sizeof(struct ws_option_tlv) +
sizeof(uint32_t));
}
/* If we have options add size of end-of-options */
if (options_length != 0) {
options_length += (uint32_t)sizeof(struct ws_option);
options_length += (uint32_t)sizeof(struct ws_option_tlv);
}
block_total_length += options_length;
timestamp = (uint64_t)sec * ts_mul + (uint64_t)usec;
@ -876,7 +876,7 @@ pcapng_write_enhanced_packet_block(pcapio_writer* pfile,
if (flags != 0) {
option.type = EPB_FLAGS;
option.value_length = sizeof(uint32_t);
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option_tlv), bytes_written, err))
return false;
if (!write_to_file(pfile, (const uint8_t*)&flags, sizeof(uint32_t), bytes_written, err))
return false;
@ -885,7 +885,7 @@ pcapng_write_enhanced_packet_block(pcapio_writer* pfile,
/* write end of options */
option.type = OPT_ENDOFOPT;
option.value_length = 0;
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option_tlv), bytes_written, err))
return false;
}
@ -909,7 +909,7 @@ pcapng_write_interface_statistics_block(pcapio_writer* pfile,
#else
struct timeval now;
#endif
struct ws_option option;
struct ws_option_tlv option;
uint32_t block_total_length;
uint32_t options_length;
uint64_t timestamp;
@ -956,26 +956,26 @@ pcapng_write_interface_statistics_block(pcapio_writer* pfile,
block_total_length = (uint32_t)(sizeof(struct isb) + sizeof(uint32_t));
options_length = 0;
if (isb_ifrecv != UINT64_MAX) {
options_length += (uint32_t)(sizeof(struct ws_option) +
options_length += (uint32_t)(sizeof(struct ws_option_tlv) +
sizeof(uint64_t));
}
if (isb_ifdrop != UINT64_MAX) {
options_length += (uint32_t)(sizeof(struct ws_option) +
options_length += (uint32_t)(sizeof(struct ws_option_tlv) +
sizeof(uint64_t));
}
/* OPT_COMMENT */
options_length += pcapng_count_string_option(comment);
if (isb_starttime !=0) {
options_length += (uint32_t)(sizeof(struct ws_option) +
options_length += (uint32_t)(sizeof(struct ws_option_tlv) +
sizeof(uint64_t)); /* ISB_STARTTIME */
}
if (isb_endtime !=0) {
options_length += (uint32_t)(sizeof(struct ws_option) +
options_length += (uint32_t)(sizeof(struct ws_option_tlv) +
sizeof(uint64_t)); /* ISB_ENDTIME */
}
/* If we have options add size of end-of-options */
if (options_length != 0) {
options_length += (uint32_t)sizeof(struct ws_option);
options_length += (uint32_t)sizeof(struct ws_option_tlv);
}
block_total_length += options_length;
@ -999,7 +999,7 @@ pcapng_write_interface_statistics_block(pcapio_writer* pfile,
option.value_length = sizeof(uint64_t);
high = (uint32_t)((isb_starttime>>32) & 0xffffffff);
low = (uint32_t)(isb_starttime & 0xffffffff);
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option_tlv), bytes_written, err))
return false;
if (!write_to_file(pfile, (const uint8_t*)&high, sizeof(uint32_t), bytes_written, err))
@ -1015,7 +1015,7 @@ pcapng_write_interface_statistics_block(pcapio_writer* pfile,
option.value_length = sizeof(uint64_t);
high = (uint32_t)((isb_endtime>>32) & 0xffffffff);
low = (uint32_t)(isb_endtime & 0xffffffff);
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option_tlv), bytes_written, err))
return false;
if (!write_to_file(pfile, (const uint8_t*)&high, sizeof(uint32_t), bytes_written, err))
@ -1027,7 +1027,7 @@ pcapng_write_interface_statistics_block(pcapio_writer* pfile,
if (isb_ifrecv != UINT64_MAX) {
option.type = ISB_IFRECV;
option.value_length = sizeof(uint64_t);
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option_tlv), bytes_written, err))
return false;
if (!write_to_file(pfile, (const uint8_t*)&isb_ifrecv, sizeof(uint64_t), bytes_written, err))
@ -1036,7 +1036,7 @@ pcapng_write_interface_statistics_block(pcapio_writer* pfile,
if (isb_ifdrop != UINT64_MAX) {
option.type = ISB_IFDROP;
option.value_length = sizeof(uint64_t);
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option_tlv), bytes_written, err))
return false;
if (!write_to_file(pfile, (const uint8_t*)&isb_ifdrop, sizeof(uint64_t), bytes_written, err))
@ -1046,7 +1046,7 @@ pcapng_write_interface_statistics_block(pcapio_writer* pfile,
/* write end of options */
option.type = OPT_ENDOFOPT;
option.value_length = 0;
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option), bytes_written, err))
if (!write_to_file(pfile, (const uint8_t*)&option, sizeof(struct ws_option_tlv), bytes_written, err))
return false;
}

View File

@ -28,6 +28,7 @@
#include <conio.h>
#endif
#include "clopts_common.h"
#include "file_util.h"
#include "time_util.h"
#include "to_str.h"
@ -368,19 +369,6 @@ enum ws_log_level ws_log_set_level_str(const char *str_level)
}
static const char *opt_level = "--log-level";
static const char *opt_domain = "--log-domain";
/* Alias "domain" and "domains". */
static const char *opt_domain_s = "--log-domains";
static const char *opt_file = "--log-file";
static const char *opt_fatal = "--log-fatal";
static const char *opt_fatal_domain = "--log-fatal-domain";
/* Alias "domain" and "domains". */
static const char *opt_fatal_domain_s = "--log-fatal-domains";
static const char *opt_debug = "--log-debug";
static const char *opt_noisy = "--log-noisy";
static void print_err(void (*vcmdarg_err)(const char *, va_list ap),
int exit_failure,
const char *fmt, ...)
@ -397,277 +385,92 @@ static void print_err(void (*vcmdarg_err)(const char *, va_list ap),
exit(exit_failure);
}
/*
* This tries to convert old log level preference to a wslog
* configuration. The string must start with "console.log.level:"
* It receives an argv for { '-o', 'console.log.level:nnn', ...} or
* { '-oconsole.log.level:nnn', ...}.
*/
static void
parse_console_compat_option(char *argv[],
void (*vcmdarg_err)(const char *, va_list ap),
int ws_log_parse_args(int* argc, char* argv[],
const char* optstring, const struct ws_option* long_options,
void (*vcmdarg_err)(const char*, va_list ap),
int exit_failure)
{
const char *mask_str;
uint32_t mask;
enum ws_log_level level;
int opt;
ASSERT(argv != NULL);
/* Save the global setting of erroring on unknown options, because this list will probably contain application options
not handled here */
int old_ws_opterr = ws_opterr;
if (argv[0] == NULL)
return;
/* Clear erroring on unknown options */
ws_opterr = 0;
if (strcmp(argv[0], "-o") == 0) {
if (argv[1] == NULL ||
!g_str_has_prefix(argv[1], "console.log.level:")) {
/* Not what we were looking for. */
return;
}
mask_str = argv[1] + strlen("console.log.level:");
}
else if (g_str_has_prefix(argv[0], "-oconsole.log.level:")) {
mask_str = argv[0] + strlen("-oconsole.log.level:");
}
else {
/* Not what we were looking for. */
return;
}
while ((opt = ws_getopt_long_only(*argc, argv, optstring, long_options, NULL)) != -1) {
print_err(vcmdarg_err, LOG_ARGS_NOEXIT,
"Option 'console.log.level' is deprecated, consult '--help' "
"for diagnostic message options.");
if (*mask_str == '\0') {
switch (opt)
{
case LONGOPT_WSLOG_LOG_LEVEL:
if (ws_log_set_level_str(ws_optarg) == LOG_LEVEL_NONE) {
print_err(vcmdarg_err, exit_failure,
"Missing value to 'console.log.level' option.");
return;
"Invalid log level \"%s\".\n", ws_optarg);
}
break;
if (!ws_basestrtou32(mask_str, NULL, &mask, 10)) {
print_err(vcmdarg_err, exit_failure,
"%s is not a valid decimal number.", mask_str);
return;
}
case LONGOPT_WSLOG_LOG_DOMAIN:
ws_log_set_domain_filter(ws_optarg);
break;
/*
* The lowest priority bit in the mask defines the level.
*/
if (mask & G_LOG_LEVEL_DEBUG)
level = LOG_LEVEL_DEBUG;
else if (mask & G_LOG_LEVEL_INFO)
level = LOG_LEVEL_INFO;
else if (mask & G_LOG_LEVEL_MESSAGE)
level = LOG_LEVEL_MESSAGE;
else if (mask & G_LOG_LEVEL_WARNING)
level = LOG_LEVEL_WARNING;
else if (mask & G_LOG_LEVEL_CRITICAL)
level = LOG_LEVEL_CRITICAL;
else if (mask & G_LOG_LEVEL_ERROR)
level = LOG_LEVEL_ERROR;
else
level = LOG_LEVEL_NONE;
if (level == LOG_LEVEL_NONE) {
/* Some values (like zero) might not contain any meaningful bits.
* Throwing an error in that case seems appropriate. */
print_err(vcmdarg_err, exit_failure,
"Value %s is not a valid log mask.", mask_str);
return;
}
ws_log_set_level(level);
}
/* Match "arg_name=value" or "arg_name value" to opt_name. */
static bool optequal(const char *arg, const char *opt)
{
ASSERT(arg);
ASSERT(opt);
#define ARGEND(arg) (*(arg) == '\0' || *(arg) == ' ' || *(arg) == '=')
while (!ARGEND(arg) && *opt != '\0') {
if (*arg != *opt) {
return false;
}
arg += 1;
opt += 1;
}
if (ARGEND(arg) && *opt == '\0') {
return true;
}
return false;
}
int ws_log_parse_args(int *argc_ptr, char *argv[],
void (*vcmdarg_err)(const char *, va_list ap),
int exit_failure)
{
char **ptr = argv;
int count = *argc_ptr;
int ret = 0;
size_t optlen;
const char *option, *value;
int extra;
if (argc_ptr == NULL || argv == NULL)
return -1;
#ifdef WS_DEBUG
/* Assert ws_log_init() was called before ws_log_parse_args(). */
ASSERT(init_complete);
#endif
/* Configure from command line. */
while (*ptr != NULL) {
if (optequal(*ptr, opt_level)) {
option = opt_level;
optlen = strlen(opt_level);
}
else if (optequal(*ptr, opt_domain)) {
option = opt_domain;
optlen = strlen(opt_domain);
}
else if (optequal(*ptr, opt_domain_s)) {
option = opt_domain; /* Alias */
optlen = strlen(opt_domain_s);
}
else if (optequal(*ptr, opt_fatal_domain)) {
option = opt_fatal_domain;
optlen = strlen(opt_fatal_domain);
}
else if (optequal(*ptr, opt_fatal_domain_s)) {
option = opt_fatal_domain; /* Alias */
optlen = strlen(opt_fatal_domain_s);
}
else if (optequal(*ptr, opt_file)) {
option = opt_file;
optlen = strlen(opt_file);
}
else if (optequal(*ptr, opt_fatal)) {
option = opt_fatal;
optlen = strlen(opt_fatal);
}
else if (optequal(*ptr, opt_debug)) {
option = opt_debug;
optlen = strlen(opt_debug);
}
else if (optequal(*ptr, opt_noisy)) {
option = opt_noisy;
optlen = strlen(opt_noisy);
}
else {
/* Check is we have the old '-o console.log.level' flag,
* or '-oconsole.log.level', for backward compatibility.
* Then if we do ignore it after processing and let the
* preferences module handle it later. */
if (*(*ptr + 0) == '-' && *(*ptr + 1) == 'o') {
parse_console_compat_option(ptr, vcmdarg_err, exit_failure);
}
ptr += 1;
count -= 1;
continue;
}
value = *ptr + optlen;
/* Two possibilities:
* --<option> <value>
* or
* --<option>=<value>
*/
if (value[0] == '\0') {
/* value is separated with blank space */
value = *(ptr + 1);
extra = 1;
if (value == NULL || !*value || *value == '-') {
/* If the option value after the blank starts with '-' assume
* it is another option. */
print_err(vcmdarg_err, exit_failure,
"Option \"%s\" requires a value.\n", *ptr);
option = NULL;
extra = 0;
ret += 1;
}
}
else if (value[0] == '=') {
/* value is after equals */
value += 1;
extra = 0;
}
else {
/* Option isn't known. */
ptr += 1;
count -= 1;
continue;
}
if (option == opt_level) {
if (ws_log_set_level_str(value) == LOG_LEVEL_NONE) {
print_err(vcmdarg_err, exit_failure,
"Invalid log level \"%s\".\n", value);
ret += 1;
}
}
else if (option == opt_domain) {
ws_log_set_domain_filter(value);
}
else if (option == opt_fatal_domain) {
ws_log_set_fatal_domain_filter(value);
}
else if (option == opt_file) {
if (value == NULL) {
print_err(vcmdarg_err, exit_failure,
"Option '%s' requires an argument.\n",
option);
ret += 1;
}
else {
FILE *fp = ws_fopen(value, "w");
case LONGOPT_WSLOG_LOG_FILE:
{
FILE* fp = ws_fopen(ws_optarg, "w");
if (fp == NULL) {
print_err(vcmdarg_err, exit_failure,
"Error opening file '%s' for writing: %s.\n",
value, g_strerror(errno));
ret += 1;
ws_optarg, g_strerror(errno));
}
else {
ws_log_add_custom_file(fp);
}
}
}
else if (option == opt_fatal) {
if (ws_log_set_fatal_level_str(value) == LOG_LEVEL_NONE) {
break;
case LONGOPT_WSLOG_LOG_FATAL:
if (ws_log_set_fatal_level_str(ws_optarg) == LOG_LEVEL_NONE) {
print_err(vcmdarg_err, exit_failure,
"Fatal log level must be \"critical\" or "
"\"warning\", not \"%s\".\n", value);
ret += 1;
"Fatal log level must be \"critical\" or \"warning\", not \"%s\".\n", ws_optarg);
}
break;
case LONGOPT_WSLOG_LOG_FATAL_DOMAIN:
ws_log_set_fatal_domain_filter(ws_optarg);
break;
case LONGOPT_WSLOG_LOG_DEBUG:
ws_log_set_debug_filter(ws_optarg);
break;
case LONGOPT_WSLOG_LOG_NOISY:
ws_log_set_noisy_filter(ws_optarg);
break;
default:
/* Ignore options not found because they are probably supported by the application */
break;
}
else if (option == opt_debug) {
ws_log_set_debug_filter(value);
}
else if (option == opt_noisy) {
ws_log_set_noisy_filter(value);
}
else {
/* Option value missing or invalid, do nothing. */
}
/*
* We found a log option. We will remove it from
* the argv by moving up the other strings in the array. This is
* so that it doesn't generate an unrecognized option
* error further along in the initialization process.
*/
/* Include the terminating NULL in the memmove. */
memmove(ptr, ptr + 1 + extra, (count - extra) * sizeof(*ptr));
/* No need to increment ptr here. */
count -= (1 + extra);
*argc_ptr -= (1 + extra);
/* Restore the global setting of erroring on unknown options */
ws_opterr = old_ws_opterr;
ws_optreset = 1;
return 0;
}
bool ws_log_is_wslog_arg(int arg)
{
static const struct ws_option test_options[] = {
LONGOPT_WSLOG
{0, 0, 0, 0 }
};
const struct ws_option* option = test_options;
while (option->val != 0) {
if (option->val == arg)
return true;
option++;
}
return ret;
return false;
}

View File

@ -23,6 +23,7 @@
#include <ws_attributes.h>
#include <ws_log_defs.h>
#include <ws_posix_compat.h>
#include "ws_getopt.h"
#ifdef WS_LOG_DOMAIN
#define _LOG_DOMAIN WS_LOG_DOMAIN
@ -218,15 +219,49 @@ void ws_log_set_writer_with_data(ws_log_writer_cb *writer,
#define LOG_ARGS_NOEXIT -1
#define LONGOPT_WSLOG_BASE LONGOPT_BASE_APPLICATION+1000
#define LONGOPT_WSLOG_LOG_LEVEL LONGOPT_WSLOG_BASE+1
#define LONGOPT_WSLOG_LOG_DOMAIN LONGOPT_WSLOG_BASE+2
#define LONGOPT_WSLOG_LOG_FILE LONGOPT_WSLOG_BASE+3
#define LONGOPT_WSLOG_LOG_FATAL LONGOPT_WSLOG_BASE+4
#define LONGOPT_WSLOG_LOG_FATAL_DOMAIN LONGOPT_WSLOG_BASE+5
#define LONGOPT_WSLOG_LOG_DEBUG LONGOPT_WSLOG_BASE+6
#define LONGOPT_WSLOG_LOG_NOISY LONGOPT_WSLOG_BASE+7
/** Logging options for command line
*/
#define LONGOPT_WSLOG \
{"log-level", ws_required_argument, NULL, LONGOPT_WSLOG_LOG_LEVEL}, \
{"log-domain", ws_required_argument, NULL, LONGOPT_WSLOG_LOG_DOMAIN}, \
/* Alias "domain" and "domains". */ \
{"log-domains", ws_required_argument, NULL, LONGOPT_WSLOG_LOG_DOMAIN}, \
{"log-file", ws_required_argument, NULL, LONGOPT_WSLOG_LOG_FILE}, \
{"log-fatal", ws_required_argument, NULL, LONGOPT_WSLOG_LOG_FATAL}, \
/* Alias "domain" and "domains". */ \
{"log-fatal-domain", ws_required_argument, NULL, LONGOPT_WSLOG_LOG_FATAL_DOMAIN}, \
{"log-fatal-domains", ws_required_argument, NULL, LONGOPT_WSLOG_LOG_FATAL_DOMAIN}, \
{"log-debug", ws_required_argument, NULL, LONGOPT_WSLOG_LOG_DEBUG}, \
{"log-noisy", ws_required_argument, NULL, LONGOPT_WSLOG_LOG_NOISY},
/** Parses the command line arguments for log options.
*
* Returns zero for no error, non-zero for one or more invalid options.
*/
WS_DLL_PUBLIC
int ws_log_parse_args(int *argc_ptr, char *argv[],
const char* optstring, const struct ws_option* long_options,
void (*vcmdarg_err)(const char *, va_list ap),
int exit_failure);
/** Determine if command line argument is used by wslog
*
* Used when applications are strict about command line arguments passed to it,
* but shouldn't be handling these themselves
*/
WS_DLL_PUBLIC
bool ws_log_is_wslog_arg(int arg);
/** Initializes the logging code.
*