2 * Common command line handling between GUIs
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
20 #include <ws_exit_codes.h>
21 #include <wsutil/ws_getopt.h>
23 #include <wsutil/version_info.h>
25 #include <wsutil/clopts_common.h>
26 #include <wsutil/cmdarg_err.h>
27 #include <wsutil/filesystem.h>
28 #include <wsutil/ws_assert.h>
30 #include <wsutil/console_win32.h>
33 #include <epan/ex-opt.h>
34 #include <epan/packet.h>
35 #include <epan/proto.h>
36 #include <epan/prefs.h>
37 #include <epan/prefs-int.h>
38 #include <epan/stat_tap_ui.h>
40 #include "capture_opts.h"
41 #include "persfilepath_opt.h"
42 #include "preference_utils.h"
44 #include "decode_as_utils.h"
48 #include "ui/dissect_opts.h"
50 #include "ui/commandline.h"
52 commandline_param_info_t global_commandline_info
;
54 capture_options global_capture_opts
;
57 commandline_print_usage(bool for_help_option
) {
64 if (for_help_option
) {
65 show_help_header("Interactively dump and analyze network traffic.");
70 fprintf(output
, "\n");
71 fprintf(output
, "Usage: wireshark [options] ... [ <infile> ]\n");
72 fprintf(output
, "\n");
75 fprintf(output
, "Capture interface:\n");
76 fprintf(output
, " -i <interface>, --interface <interface>\n");
77 fprintf(output
, " name or idx of interface (def: first non-loopback)\n");
78 fprintf(output
, " -f <capture filter> packet filter in libpcap filter syntax\n");
79 fprintf(output
, " -s <snaplen>, --snapshot-length <snaplen>\n");
80 #ifdef HAVE_PCAP_CREATE
81 fprintf(output
, " packet snapshot length (def: appropriate maximum)\n");
83 fprintf(output
, " packet snapshot length (def: %u)\n", WTAP_MAX_PACKET_SIZE_STANDARD
);
85 fprintf(output
, " -p, --no-promiscuous-mode\n");
86 fprintf(output
, " don't capture in promiscuous mode\n");
87 #ifdef HAVE_PCAP_CREATE
88 fprintf(output
, " -I, --monitor-mode capture in monitor mode, if available\n");
90 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
91 fprintf(output
, " -B <buffer size>, --buffer-size <buffer size>\n");
92 fprintf(output
, " size of kernel buffer (def: %dMB)\n", DEFAULT_CAPTURE_BUFFER_SIZE
);
94 fprintf(output
, " -y <link type>, --linktype <link type>\n");
95 fprintf(output
, " link layer type (def: first appropriate)\n");
96 fprintf(output
, " --time-stamp-type <type> timestamp method for interface\n");
97 fprintf(output
, " -D, --list-interfaces print list of interfaces and exit\n");
98 fprintf(output
, " -L, --list-data-link-types\n");
99 fprintf(output
, " print list of link-layer types of iface and exit\n");
100 fprintf(output
, " --list-time-stamp-types print list of timestamp types for iface and exit\n");
101 fprintf(output
, "\n");
102 fprintf(output
, "Capture display:\n");
103 fprintf(output
, " -k start capturing immediately (def: do nothing)\n");
104 fprintf(output
, " -S update packet display when new packets are captured\n");
105 fprintf(output
, " --update-interval interval between updates with new packets (def: %dms)\n", DEFAULT_UPDATE_INTERVAL
);
106 fprintf(output
, " -l turn on automatic scrolling while -S is in use\n");
107 fprintf(output
, "Capture stop conditions:\n");
108 fprintf(output
, " -c <packet count> stop after n packets (def: infinite)\n");
109 fprintf(output
, " -a <autostop cond.> ..., --autostop <autostop cond.> ...\n");
110 fprintf(output
, " duration:NUM - stop after NUM seconds\n");
111 fprintf(output
, " filesize:NUM - stop this file after NUM KB\n");
112 fprintf(output
, " files:NUM - stop after NUM files\n");
113 fprintf(output
, " packets:NUM - stop after NUM packets\n");
114 /*fprintf(output, "\n");*/
115 fprintf(output
, "Capture output:\n");
116 fprintf(output
, " -b <ringbuffer opt.> ..., --ring-buffer <ringbuffer opt.>\n");
117 fprintf(output
, " duration:NUM - switch to next file after NUM secs\n");
118 fprintf(output
, " filesize:NUM - switch to next file after NUM KB\n");
119 fprintf(output
, " files:NUM - ringbuffer: replace after NUM files\n");
120 fprintf(output
, " packets:NUM - switch to next file after NUM packets\n");
121 fprintf(output
, " interval:NUM - switch to next file when the time is\n");
122 fprintf(output
, " an exact multiple of NUM secs\n");
123 #endif /* HAVE_LIBPCAP */
124 #ifdef HAVE_PCAP_REMOTE
125 fprintf(output
, "RPCAP options:\n");
126 fprintf(output
, " -A <user>:<password> use RPCAP password authentication\n");
128 /*fprintf(output, "\n");*/
129 fprintf(output
, "Input file:\n");
130 fprintf(output
, " -r <infile>, --read-file <infile>\n");
131 fprintf(output
, " set the filename to read from (no pipes or stdin!)\n");
133 fprintf(output
, "\n");
134 fprintf(output
, "Processing:\n");
135 fprintf(output
, " -R <read filter>, --read-filter <read filter>\n");
136 fprintf(output
, " packet filter in Wireshark display filter syntax\n");
137 fprintf(output
, " -n disable all name resolutions (def: all enabled)\n");
138 // Note: the order of the flags here matches the options in the settings dialog e.g. "dsN" only have an effect if "n" is set
139 fprintf(output
, " -N <name resolve flags> enable specific name resolution(s): \"mtndsNvg\"\n");
140 fprintf(output
, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE
);
141 fprintf(output
, " \"Decode As\", see the man page for details\n");
142 fprintf(output
, " Example: tcp.port==8888,http\n");
143 fprintf(output
, " --enable-protocol <proto_name>\n");
144 fprintf(output
, " enable dissection of proto_name\n");
145 fprintf(output
, " --disable-protocol <proto_name>\n");
146 fprintf(output
, " disable dissection of proto_name\n");
147 fprintf(output
, " --only-protocols <proto_name>\n");
148 fprintf(output
, " Only enable dissection of these protocols, comma\n");
149 fprintf(output
, " separated. Disable everything else\n");
150 fprintf(output
, " --disable-all-protocols\n");
151 fprintf(output
, " Disable dissection of all protocols\n");
152 fprintf(output
, " --enable-heuristic <short_name>\n");
153 fprintf(output
, " enable dissection of heuristic protocol\n");
154 fprintf(output
, " --disable-heuristic <short_name>\n");
155 fprintf(output
, " disable dissection of heuristic protocol\n");
157 fprintf(output
, "\n");
158 fprintf(output
, "User interface:\n");
159 fprintf(output
, " -C <config profile> start with specified configuration profile\n");
160 fprintf(output
, " -H hide the capture info dialog during packet capture\n");
161 fprintf(output
, " -Y <display filter>, --display-filter <display filter>\n");
162 fprintf(output
, " start with the given display filter\n");
163 fprintf(output
, " -g <packet number> go to specified packet number after \"-r\"\n");
164 fprintf(output
, " -J <jump filter> jump to the first packet matching the (display)\n");
165 fprintf(output
, " filter\n");
166 fprintf(output
, " -j search backwards for a matching packet after \"-J\"\n");
167 fprintf(output
, " -t (a|ad|adoy|d|dd|e|r|u|ud|udoy)[.[N]]|.[N]\n");
168 fprintf(output
, " format of time stamps (def: r: rel. to first)\n");
169 fprintf(output
, " -u s|hms output format of seconds (def: s: seconds)\n");
170 fprintf(output
, " -X <key>:<value> eXtension options, see man page for details\n");
171 fprintf(output
, " -z <statistics> show various statistics, see man page for details\n");
173 fprintf(output
, "\n");
174 fprintf(output
, "Output:\n");
175 fprintf(output
, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
177 fprintf(output
, " -F <capture type> set the output file type; default is pcapng.\n");
178 fprintf(output
, " an empty \"-F\" option will list the file types.\n");
179 fprintf(output
, " --capture-comment <comment>\n");
180 fprintf(output
, " add a capture file comment, if supported\n");
182 fprintf(output
, " --temp-dir <directory> write temporary files to this directory\n");
183 fprintf(output
, " (default: %s)\n", g_get_tmp_dir());
184 fprintf(output
, "\n");
186 ws_log_print_usage(output
);
188 fprintf(output
, "\n");
189 fprintf(output
, "Miscellaneous:\n");
190 fprintf(output
, " -h, --help display this help and exit\n");
191 fprintf(output
, " -v, --version display version info and exit\n");
192 fprintf(output
, " -P <key>:<path> persconf:path - personal configuration files\n");
193 fprintf(output
, " persdata:path - personal data files\n");
194 fprintf(output
, " -o <name>:<value> ... override preference or recent setting\n");
195 fprintf(output
, " -K <keytab> keytab file to use for kerberos decryption\n");
197 fprintf(output
, " --display <X display> X display to use\n");
199 fprintf(output
, " --fullscreen start Wireshark in full screen\n");
206 #define LONGOPT_FULL_SCREEN LONGOPT_BASE_GUI+1
207 #define LONGOPT_CAPTURE_COMMENT LONGOPT_BASE_GUI+2
209 #define OPTSTRING OPTSTRING_CAPTURE_COMMON OPTSTRING_DISSECT_COMMON OPTSTRING_READ_CAPTURE_COMMON "C:g:HhjJ:klm:o:P:Svw:X:z:"
210 static const struct ws_option long_options
[] = {
211 {"help", ws_no_argument
, NULL
, 'h'},
212 {"version", ws_no_argument
, NULL
, 'v'},
213 {"fullscreen", ws_no_argument
, NULL
, LONGOPT_FULL_SCREEN
},
214 {"capture-comment", ws_required_argument
, NULL
, LONGOPT_CAPTURE_COMMENT
},
215 LONGOPT_CAPTURE_COMMON
216 LONGOPT_DISSECT_COMMON
217 LONGOPT_READ_CAPTURE_COMMON
220 static const char optstring
[] = OPTSTRING
;
223 static void print_no_capture_support_error(void)
225 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
229 void commandline_early_options(int argc
, char *argv
[])
238 bool capture_option_specified
;
242 * In order to have the -X opts assigned before the wslua machine starts
243 * we need to call getopt_long before epan_init() gets called.
245 * In addition, we process "console only" parameters (ones where we
246 * send output to the console and exit) here, so we don't start GUI
247 * if we're only showing command-line help or version information.
249 * XXX - this pre-scan is done before we start GUI, so we haven't
250 * run "GUI init function" on the arguments. That means that GUI-specific
251 * arguments have not been removed from the argument list; those arguments
252 * begin with "--", and will be treated as an error by getopt_long().
254 * We thus ignore errors - *and* set "ws_opterr" to 0 to suppress the
257 * In order to handle, for example, -o options, we also need to call it
258 * *after* epan_init() gets called, so that the dissectors have had a
259 * chance to register their preferences, so we have another getopt_long()
262 * XXX - can we do this all with one getopt_long() call, saving the
263 * arguments we can't handle until after initializing libwireshark,
264 * and then process them after initializing libwireshark?
266 * Note that we don't want to initialize libwireshark until after the
267 * GUI is up, as that can take a while, and we want a window of some
268 * sort up to show progress while that's happening.
273 capture_option_specified
= false;
275 while ((opt
= ws_getopt_long(argc
, argv
, optstring
, long_options
, NULL
)) != -1) {
277 case 'C': /* Configuration Profile */
278 if (profile_exists (ws_optarg
, false)) {
279 set_profile_name (ws_optarg
);
280 } else if (profile_exists (ws_optarg
, true)) {
281 char *pf_dir_path
, *pf_dir_path2
, *pf_filename
;
282 /* Copy from global profile */
283 if (create_persconffile_profile(ws_optarg
, &pf_dir_path
) == -1) {
284 cmdarg_err("Can't create directory\n\"%s\":\n%s.",
285 pf_dir_path
, g_strerror(errno
));
288 exit(WS_EXIT_INVALID_FILE
);
290 if (copy_persconffile_profile(ws_optarg
, ws_optarg
, true, &pf_filename
,
291 &pf_dir_path
, &pf_dir_path2
) == -1) {
292 cmdarg_err("Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
293 pf_filename
, pf_dir_path2
, pf_dir_path
, g_strerror(errno
));
297 g_free(pf_dir_path2
);
298 exit(WS_EXIT_INVALID_FILE
);
300 set_profile_name (ws_optarg
);
302 cmdarg_err("Configuration Profile \"%s\" does not exist", ws_optarg
);
306 case 'D': /* Print a list of capture devices and exit */
308 exit_status
= EXIT_SUCCESS
;
309 if_list
= capture_interface_list(&err
, &err_str
, NULL
);
312 * An error occurred when fetching the local
313 * interfaces. Report it.
318 cmdarg_err("%s", err_str
);
320 exit_status
= WS_EXIT_PCAP_ERROR
;
322 if (if_list
== NULL
) {
324 * No interfaces were found. If that's not the
325 * result of an error when fetching the local
326 * interfaces, let the user know.
329 cmdarg_err("There are no interfaces on which a capture can be done");
330 exit_status
= WS_EXIT_NO_INTERFACES
;
337 capture_opts_print_interfaces(if_list
);
338 free_interface_list(if_list
);
343 #else /* HAVE_LIBPCAP */
344 capture_option_specified
= true;
345 #endif /* HAVE_LIBPCAP */
347 case 'h': /* Print help and exit */
348 commandline_print_usage(true);
353 if (strcmp(ws_optarg
, "-") == 0)
354 set_stdin_capture(true);
357 case 'P': /* Personal file directory path settings - change these before the Preferences and alike are processed */
358 if (!persfilepath_opt(opt
, ws_optarg
)) {
359 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", ws_optarg
);
363 case 'v': /* Show version and exit */
375 * Extension command line options have to be processed before
376 * we call epan_init() as they are supposed to be used by dissectors
377 * or taps very early in the registration process.
379 ex_opt_add(ws_optarg
);
381 case '?': /* Ignore errors - the "real" scan will catch them. */
387 if (ex_opt_count("lua_script") > 0) {
388 cmdarg_err("This version of Wireshark was not built with support for Lua scripting.");
394 if (capture_option_specified
) {
395 print_no_capture_support_error();
396 commandline_print_usage(false);
402 void commandline_override_prefs(int argc
, char *argv
[], bool opt_reset
)
407 * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1.
409 * Ignore errors and keep ws_opterr as 0; error messages will be printed
410 * later by command_other_options()
418 /* Initialize with default values */
419 global_commandline_info
.user_opts
= NULL
;
421 while ((opt
= ws_getopt_long(argc
, argv
, optstring
, long_options
, NULL
)) != -1) {
423 case 'o': /* Override preference from command line */
427 switch (prefs_set_pref(ws_optarg
, &errmsg
)) {
429 global_commandline_info
.user_opts
=
430 g_slist_prepend(global_commandline_info
.user_opts
,
431 g_strdup(ws_optarg
));
433 case PREFS_SET_SYNTAX_ERR
:
434 cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg
,
435 errmsg
? ": " : "", errmsg
? errmsg
: "");
439 case PREFS_SET_NO_SUCH_PREF
:
440 /* not a preference, might be a recent setting */
441 switch (recent_set_arg(ws_optarg
)) {
444 case PREFS_SET_SYNTAX_ERR
:
445 /* shouldn't happen, checked already above */
446 cmdarg_err("Invalid -o flag \"%s\"", ws_optarg
);
449 case PREFS_SET_NO_SUCH_PREF
:
450 case PREFS_SET_OBSOLETE
:
451 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
456 ws_assert_not_reached();
459 case PREFS_SET_OBSOLETE
:
460 /* obsolete preference, might be a recent setting */
461 if (recent_set_arg(ws_optarg
) != PREFS_SET_OK
) {
462 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
468 ws_assert_not_reached();
473 case '?': /* Ignore errors - the "real" scan will catch them. */
478 /* Since we prepended each option when processing `-o`, reverse the list
479 * in case the order of options becomes meaningful.
481 global_commandline_info
.user_opts
= g_slist_reverse(global_commandline_info
.user_opts
);
485 void commandline_other_options(int argc
, char *argv
[], bool opt_reset
)
488 bool arg_error
= false;
490 const char *list_option_supplied
= NULL
;
493 bool capture_option_specified
;
497 * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1.
499 * Also reset ws_opterr to 1, so that error messages are printed by
502 * XXX - if we want to control all the command-line option errors, so
503 * that we can display them where we choose (e.g., in a window), we'd
504 * want to leave ws_opterr as 0, and produce our own messages using ws_optopt.
505 * We'd have to check the value of ws_optopt to see if it's a valid option
506 * letter, in which case *presumably* the error is "this option requires
507 * an argument but none was specified", or not a valid option letter,
508 * in which case *presumably* the error is "this option isn't valid".
509 * Some versions of getopt() let you supply a option string beginning
510 * with ':', which means that getopt() will return ':' rather than '?'
511 * for "this option requires an argument but none was specified", but
512 * not all do. But we're now using getopt_long() - what does it do?
520 /* Initialize with default values */
521 global_commandline_info
.jump_backwards
= SD_FORWARD
;
522 global_commandline_info
.go_to_packet
= 0;
523 global_commandline_info
.jfilter
= NULL
;
524 global_commandline_info
.cf_name
= NULL
;
525 global_commandline_info
.rfilter
= NULL
;
526 global_commandline_info
.dfilter
= NULL
;
528 global_commandline_info
.start_capture
= false;
529 global_commandline_info
.list_link_layer_types
= false;
530 global_commandline_info
.list_timestamp_types
= false;
531 global_commandline_info
.quit_after_cap
= getenv("WIRESHARK_QUIT_AFTER_CAPTURE") ? true : false;
532 global_commandline_info
.capture_comments
= NULL
;
534 global_commandline_info
.full_screen
= false;
536 while ((opt
= ws_getopt_long(argc
, argv
, optstring
, long_options
, NULL
)) != -1) {
538 /*** capture option specific ***/
539 case 'a': /* autostop criteria */
540 case 'b': /* Ringbuffer option */
541 case 'c': /* Capture xxx packets */
542 case 'f': /* capture filter */
543 case 'F': /* capture file type */
544 case 'H': /* Hide capture info dialog box */
545 case 'p': /* Don't capture in promiscuous mode */
546 case 'i': /* Use interface x */
547 case LONGOPT_SET_TSTAMP_TYPE
: /* Set capture timestamp type */
548 case LONGOPT_CAPTURE_TMPDIR
: /* capture temp directory */
549 case LONGOPT_UPDATE_INTERVAL
: /* sync pipe update interval */
550 #ifdef HAVE_PCAP_CREATE
551 case 'I': /* Capture in monitor mode, if available */
553 #ifdef HAVE_PCAP_REMOTE
554 case 'A': /* Authentication */
556 case 's': /* Set the snapshot (capture) length */
557 case 'S': /* "Sync" mode: used for following file ala tail -f */
558 case 'w': /* Write to capture file xxx */
559 case 'y': /* Set the pcap data link type */
560 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
561 case 'B': /* Buffer size */
564 status
= capture_opts_add_opt(&global_capture_opts
, opt
, ws_optarg
);
566 exit_application(status
);
569 capture_option_specified
= true;
574 /*** all non capture option specific ***/
576 /* Configuration profile settings were already processed just ignore them this time*/
578 case 'j': /* Search backwards for a matching packet from filter in option J */
579 global_commandline_info
.jump_backwards
= SD_BACKWARD
;
581 case 'g': /* Go to packet with the given packet number */
582 global_commandline_info
.go_to_packet
= get_nonzero_uint32(ws_optarg
, "go to packet");
584 case 'J': /* Jump to the first packet which matches the filter criteria */
585 global_commandline_info
.jfilter
= ws_optarg
;
587 case 'k': /* Start capture immediately */
589 global_commandline_info
.start_capture
= true;
591 capture_option_specified
= true;
595 case 'l': /* Automatic scrolling in live capture mode */
597 recent
.capture_auto_scroll
= true;
599 capture_option_specified
= true;
603 case 'L': /* Print list of link-layer types and exit */
605 global_commandline_info
.list_link_layer_types
= true;
606 list_option_supplied
= "-L";
608 capture_option_specified
= true;
612 case LONGOPT_LIST_TSTAMP_TYPES
:
614 global_commandline_info
.list_timestamp_types
= true;
615 list_option_supplied
= "--list-time-stamp-types";
617 capture_option_specified
= true;
621 case 'o': /* Override preference from command line */
622 /* Pref overrides were already processed just ignore them this time*/
625 /* Path settings were already processed just ignore them this time*/
627 case 'r': /* Read capture file xxx */
628 /* We may set "last_open_dir" to "cf_name", and if we change
629 "last_open_dir" later, we free the old value, so we have to
630 set "cf_name" to something that's been allocated. */
631 global_commandline_info
.cf_name
= g_strdup(ws_optarg
);
633 case 'R': /* Read file filter */
634 global_commandline_info
.rfilter
= ws_optarg
;
637 /* ext ops were already processed just ignore them this time*/
640 global_commandline_info
.dfilter
= ws_optarg
;
643 /* We won't call the init function for the stat this soon
644 as it would disallow MATE's fields (which are registered
645 by the preferences set callback) from being used as
646 part of a tap filter. Instead, we just add the argument
647 to a list of stat arguments. */
648 if (strcmp("help", ws_optarg
) == 0) {
649 fprintf(stderr
, "wireshark: The available statistics for the \"-z\" option are:\n");
650 list_stat_cmd_args();
653 if (!process_stat_cmd_arg(ws_optarg
)) {
654 cmdarg_err("Invalid -z argument.");
655 cmdarg_err_cont(" -z argument must be one of :");
656 list_stat_cmd_args();
660 case 'd': /* Decode as rule */
661 case 'K': /* Kerberos keytab file */
662 case 'n': /* No name resolution */
663 case 'N': /* Select what types of addresses/port #s to resolve */
664 case 't': /* time stamp type */
665 case 'u': /* Seconds type */
666 case LONGOPT_DISABLE_PROTOCOL
: /* disable dissection of protocol */
667 case LONGOPT_ENABLE_HEURISTIC
: /* enable heuristic dissection of protocol */
668 case LONGOPT_DISABLE_HEURISTIC
: /* disable heuristic dissection of protocol */
669 case LONGOPT_ENABLE_PROTOCOL
: /* enable dissection of protocol (that is disabled by default) */
670 case LONGOPT_ONLY_PROTOCOLS
: /* enable dissection of these comma separated protocols only */
671 case LONGOPT_DISABLE_ALL_PROTOCOLS
: /* disable dissection of all protocols */
672 if (!dissect_opts_handle_opt(opt
, ws_optarg
))
675 case LONGOPT_FULL_SCREEN
:
676 global_commandline_info
.full_screen
= true;
679 case LONGOPT_CAPTURE_COMMENT
: /* capture comment */
680 if (global_commandline_info
.capture_comments
== NULL
) {
681 global_commandline_info
.capture_comments
= g_ptr_array_new_with_free_func(g_free
);
683 g_ptr_array_add(global_commandline_info
.capture_comments
, g_strdup(ws_optarg
));
685 capture_option_specified
= true;
690 case '?': /* Bad flag - print usage message */
700 if (global_commandline_info
.cf_name
!= NULL
) {
702 * Input file name specified with "-r" *and* specified as a regular
703 * command-line argument.
705 cmdarg_err("File name specified both with -r and regular argument");
709 * Input file name not specified with "-r", and a command-line argument
710 * was specified; treat it as the input file name.
712 * Yes, this is different from tshark, where non-flag command-line
713 * arguments are a filter, but this works better on GUI desktops
714 * where a command can be specified to be run to open a particular
715 * file - yes, you could have "-r" as the last part of the command,
716 * but that's a bit ugly.
718 global_commandline_info
.cf_name
= g_strdup(argv
[0]);
726 * Extra command line arguments were specified; complain.
728 cmdarg_err("Invalid argument: %s", argv
[0]);
735 if (ws_optopt
== 'F') {
736 capture_opts_list_file_types();
740 if (capture_option_specified
) {
741 print_no_capture_support_error();
744 commandline_print_usage(false);
749 if (global_commandline_info
.start_capture
&& list_option_supplied
) {
750 /* Specifying *both* is bogus. */
751 cmdarg_err("You can't specify both %s and a live capture.", list_option_supplied
);
755 if (list_option_supplied
) {
756 /* We're supposed to list the link-layer types for an interface;
757 did the user also specify a capture file to be read? */
758 if (global_commandline_info
.cf_name
) {
759 /* Yes - that's bogus. */
760 cmdarg_err("You can't specify %s and a capture file to be read.", list_option_supplied
);
763 /* No - did they specify a ring buffer option? */
764 if (global_capture_opts
.multi_files_on
) {
765 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
769 /* We're supposed to do a live capture; did the user also specify
770 a capture file to be read? */
771 if (global_commandline_info
.start_capture
&& global_commandline_info
.cf_name
) {
772 /* Yes - that's bogus. */
773 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
777 /* No - was the ring buffer option specified and, if so, does it make
779 if (global_capture_opts
.multi_files_on
) {
780 /* Ring buffer works only under certain conditions:
781 a) ring buffer does not work with temporary files;
782 b) real_time_mode and multi_files_on are mutually exclusive -
783 real_time_mode takes precedence;
784 c) it makes no sense to enable the ring buffer if the maximum
785 file size is set to "infinite". */
786 if (global_capture_opts
.save_file
== NULL
) {
787 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
788 global_capture_opts
.multi_files_on
= false;
790 if (!global_capture_opts
.has_autostop_filesize
&&
791 !global_capture_opts
.has_file_duration
&&
792 !global_capture_opts
.has_file_interval
&&
793 !global_capture_opts
.has_file_packets
) {
794 cmdarg_err("Ring buffer requested, but no maximum capture file size, duration, interval or packets were specified.");
795 /* XXX - this must be redesigned as the conditions changed */
802 /* Local function used by commandline_options_drop */
803 static int cl_find_custom(const void *elem_data
, const void *search_data
) {
804 return memcmp(elem_data
, search_data
, strlen((char *)search_data
));
807 /* Drop any options the user specified on the command line with `-o`
808 * that have the given module and preference names
810 void commandline_options_drop(const char *module_name
, const char *pref_name
) {
814 if (global_commandline_info
.user_opts
== NULL
) return;
816 opt_prefix
= ws_strdup_printf("%s.%s:", module_name
, pref_name
);
818 while (NULL
!= (elem
= g_slist_find_custom(global_commandline_info
.user_opts
,
819 (const void *)opt_prefix
, cl_find_custom
))) {
820 global_commandline_info
.user_opts
=
821 g_slist_remove_link(global_commandline_info
.user_opts
, elem
);
823 g_slist_free_1(elem
);
828 /* Reapply any options the user specified on the command line with `-o`
829 * Called in the Qt UI when reloading Lua plugins
830 * For https://gitlab.com/wireshark/wireshark/-/issues/12331
832 void commandline_options_reapply(void) {
834 GSList
*entry
= NULL
;
836 for (entry
= global_commandline_info
.user_opts
; entry
!= NULL
; entry
= g_slist_next(entry
)) {
837 /* Although these options are from the user-supplied command line,
838 * they were checked for validity before we added them to user_opts,
839 * so we don't check them again here. In the worst case, a pref is
840 * specified for a lua plugin which has been edited after Wireshark
841 * started and has had that pref removed; not worth exiting over.
844 prefs_set_pref((char *)entry
->data
, &errmsg
);
845 if (errmsg
!= NULL
) {
852 void commandline_options_apply_extcap(void) {
854 GSList
*entry
= NULL
;
857 if (prefs
.capture_no_extcap
)
860 for (entry
= global_commandline_info
.user_opts
; entry
!= NULL
; entry
= g_slist_next(entry
)) {
861 pref_arg
= (char *)entry
->data
;
862 if (g_str_has_prefix(pref_arg
, "extcap.")) {
863 switch (prefs_set_pref(pref_arg
, &errmsg
)) {
866 case PREFS_SET_SYNTAX_ERR
:
867 cmdarg_err("Invalid -o flag \"%s\"%s%s", pref_arg
,
868 errmsg
? ": " : "", errmsg
? errmsg
: "");
872 case PREFS_SET_NO_SUCH_PREF
:
873 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
877 case PREFS_SET_OBSOLETE
:
878 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
883 ws_assert_not_reached();
889 /* Free memory used to hold user-specified command line options */
890 void commandline_options_free(void) {
891 g_slist_free_full(g_steal_pointer(&global_commandline_info
.user_opts
), g_free
);