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/application_flavor.h>
26 #include <wsutil/clopts_common.h>
27 #include <wsutil/cmdarg_err.h>
28 #include <wsutil/filesystem.h>
29 #include <wsutil/ws_assert.h>
31 #include <wsutil/console_win32.h>
34 #include <epan/ex-opt.h>
35 #include <epan/packet.h>
36 #include <epan/proto.h>
37 #include <epan/prefs.h>
38 #include <epan/prefs-int.h>
39 #include <epan/stat_tap_ui.h>
41 #include "persfilepath_opt.h"
42 #include "preference_utils.h"
44 #include "decode_as_utils.h"
48 #include "ui/capture_opts.h"
50 #include "ui/dissect_opts.h"
52 #include "ui/commandline.h"
54 commandline_param_info_t global_commandline_info
;
56 capture_options global_capture_opts
;
59 commandline_print_usage(bool for_help_option
) {
66 if (for_help_option
) {
67 show_help_header("Interactively dump and analyze network traffic.");
72 fprintf(output
, "\n");
73 fprintf(output
, "Usage: %s [options] ... [ <infile> ]\n", g_get_prgname());
74 fprintf(output
, "\n");
77 fprintf(output
, "Capture interface:\n");
78 fprintf(output
, " -i <interface>, --interface <interface>\n");
79 fprintf(output
, " name or idx of interface (def: first non-loopback)\n");
80 fprintf(output
, " -f <capture filter> packet filter in libpcap filter syntax\n");
81 fprintf(output
, " -s <snaplen>, --snapshot-length <snaplen>\n");
82 #ifdef HAVE_PCAP_CREATE
83 fprintf(output
, " packet snapshot length (def: appropriate maximum)\n");
85 fprintf(output
, " packet snapshot length (def: %u)\n", WTAP_MAX_PACKET_SIZE_STANDARD
);
87 fprintf(output
, " -p, --no-promiscuous-mode\n");
88 fprintf(output
, " don't capture in promiscuous mode\n");
89 #ifdef HAVE_PCAP_CREATE
90 fprintf(output
, " -I, --monitor-mode capture in monitor mode, if available\n");
92 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
93 fprintf(output
, " -B <buffer size>, --buffer-size <buffer size>\n");
94 fprintf(output
, " size of kernel buffer in MiB (def: %dMiB)\n", DEFAULT_CAPTURE_BUFFER_SIZE
);
96 fprintf(output
, " -y <link type>, --linktype <link type>\n");
97 fprintf(output
, " link layer type (def: first appropriate)\n");
98 fprintf(output
, " --time-stamp-type <type> timestamp method for interface\n");
99 fprintf(output
, " -D, --list-interfaces print list of interfaces and exit\n");
100 fprintf(output
, " -L, --list-data-link-types\n");
101 fprintf(output
, " print list of link-layer types of iface and exit\n");
102 fprintf(output
, " --list-time-stamp-types print list of timestamp types for iface and exit\n");
103 fprintf(output
, "\n");
104 fprintf(output
, "Capture display:\n");
105 fprintf(output
, " -k start capturing immediately (def: do nothing)\n");
106 fprintf(output
, " -S update packet display when new packets are captured\n");
107 fprintf(output
, " -l turn on automatic scrolling while -S is in use\n");
108 fprintf(output
, " --update-interval interval between updates with new packets, in milliseconds (def: %dms)\n", DEFAULT_UPDATE_INTERVAL
);
109 fprintf(output
, "Capture stop conditions:\n");
110 fprintf(output
, " -c <packet count> stop after n packets (def: infinite)\n");
111 fprintf(output
, " -a <autostop cond.> ..., --autostop <autostop cond.> ...\n");
112 fprintf(output
, " duration:NUM - stop after NUM seconds\n");
113 fprintf(output
, " filesize:NUM - stop this file after NUM KB\n");
114 fprintf(output
, " files:NUM - stop after NUM files\n");
115 fprintf(output
, " packets:NUM - stop after NUM packets\n");
116 /*fprintf(output, "\n");*/
117 fprintf(output
, "Capture output:\n");
118 fprintf(output
, " -b <ringbuffer opt.> ..., --ring-buffer <ringbuffer opt.>\n");
119 fprintf(output
, " duration:NUM - switch to next file after NUM secs\n");
120 fprintf(output
, " filesize:NUM - switch to next file after NUM KB\n");
121 fprintf(output
, " files:NUM - ringbuffer: replace after NUM files\n");
122 fprintf(output
, " packets:NUM - switch to next file after NUM packets\n");
123 fprintf(output
, " interval:NUM - switch to next file when the time is\n");
124 fprintf(output
, " an exact multiple of NUM secs\n");
125 #endif /* HAVE_LIBPCAP */
126 #ifdef HAVE_PCAP_REMOTE
127 fprintf(output
, "RPCAP options:\n");
128 fprintf(output
, " -A <user>:<password> use RPCAP password authentication\n");
130 /*fprintf(output, "\n");*/
131 fprintf(output
, "Input file:\n");
132 fprintf(output
, " -r <infile>, --read-file <infile>\n");
133 fprintf(output
, " set the filename to read from (no pipes or stdin!)\n");
135 fprintf(output
, "\n");
136 fprintf(output
, "Processing:\n");
137 fprintf(output
, " -R <read filter>, --read-filter <read filter>\n");
138 fprintf(output
, " packet filter in display filter (wireshark-filter(4)) syntax\n");
139 fprintf(output
, " -n disable all name resolutions (def: all enabled)\n");
140 // 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
141 fprintf(output
, " -N <name resolve flags> enable specific name resolution(s): \"mtndsNvg\"\n");
142 fprintf(output
, " -d %s ...\n", DECODE_AS_ARG_TEMPLATE
);
143 fprintf(output
, " \"Decode As\", see the man page for details\n");
144 fprintf(output
, " Example: tcp.port==8888,http\n");
145 fprintf(output
, " --enable-protocol <proto_name>\n");
146 fprintf(output
, " enable dissection of proto_name\n");
147 fprintf(output
, " --disable-protocol <proto_name>\n");
148 fprintf(output
, " disable dissection of proto_name\n");
149 fprintf(output
, " --only-protocols <protocols>\n");
150 fprintf(output
, " Only enable dissection of these protocols, comma\n");
151 fprintf(output
, " separated. Disable everything else\n");
152 fprintf(output
, " --disable-all-protocols\n");
153 fprintf(output
, " Disable dissection of all protocols\n");
154 fprintf(output
, " --enable-heuristic <short_name>\n");
155 fprintf(output
, " enable dissection of heuristic protocol\n");
156 fprintf(output
, " --disable-heuristic <short_name>\n");
157 fprintf(output
, " disable dissection of heuristic protocol\n");
159 fprintf(output
, "\n");
160 fprintf(output
, "User interface:\n");
161 fprintf(output
, " -C <config profile> start with specified configuration profile\n");
162 fprintf(output
, " -H hide the capture info dialog during packet capture\n");
163 fprintf(output
, " -Y <display filter>, --display-filter <display filter>\n");
164 fprintf(output
, " start with the given display filter\n");
165 fprintf(output
, " -g <packet number> go to specified packet number after \"-r\"\n");
166 fprintf(output
, " -J <jump filter> jump to the first packet matching the (display)\n");
167 fprintf(output
, " filter\n");
168 fprintf(output
, " -j search backwards for a matching packet after \"-J\"\n");
169 fprintf(output
, " -t (a|ad|adoy|d|dd|e|r|u|ud|udoy)[.[N]]|.[N]\n");
170 fprintf(output
, " format of time stamps (def: r: rel. to first)\n");
171 fprintf(output
, " -u s|hms output format of seconds (def: s: seconds)\n");
172 fprintf(output
, " -X <key>:<value> eXtension options, see man page for details\n");
173 fprintf(output
, " -z <statistics> show various statistics, see man page for details\n");
175 fprintf(output
, "\n");
176 fprintf(output
, "Output:\n");
177 fprintf(output
, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
179 fprintf(output
, " -F <capture type> set the output file type; default is pcapng.\n");
180 fprintf(output
, " an empty \"-F\" option will list the file types.\n");
181 fprintf(output
, " --capture-comment <comment>\n");
182 fprintf(output
, " add a capture file comment, if supported\n");
184 fprintf(output
, " --temp-dir <directory> write temporary files to this directory\n");
185 fprintf(output
, " (default: %s)\n", g_get_tmp_dir());
186 fprintf(output
, "\n");
188 ws_log_print_usage(output
);
190 fprintf(output
, "\n");
191 fprintf(output
, "Miscellaneous:\n");
192 fprintf(output
, " -h, --help display this help and exit\n");
193 fprintf(output
, " -v, --version display version info and exit\n");
194 fprintf(output
, " -P <key>:<path> persconf:path - personal configuration files\n");
195 fprintf(output
, " persdata:path - personal data files\n");
196 fprintf(output
, " -o <name>:<value> ... override preference or recent setting\n");
197 fprintf(output
, " -K <keytab> keytab file to use for kerberos decryption\n");
199 fprintf(output
, " --display <X display> X display to use\n");
201 fprintf(output
, " --fullscreen start %s in full screen\n", application_flavor_name_proper());
208 #define LONGOPT_FULL_SCREEN LONGOPT_BASE_GUI+1
209 #define LONGOPT_CAPTURE_COMMENT LONGOPT_BASE_GUI+2
211 #define OPTSTRING OPTSTRING_CAPTURE_COMMON OPTSTRING_DISSECT_COMMON OPTSTRING_READ_CAPTURE_COMMON "C:g:HhjJ:klm:o:P:Svw:X:z:"
212 static const struct ws_option long_options
[] = {
213 {"help", ws_no_argument
, NULL
, 'h'},
214 {"version", ws_no_argument
, NULL
, 'v'},
215 {"fullscreen", ws_no_argument
, NULL
, LONGOPT_FULL_SCREEN
},
216 {"capture-comment", ws_required_argument
, NULL
, LONGOPT_CAPTURE_COMMENT
},
217 LONGOPT_CAPTURE_COMMON
218 LONGOPT_DISSECT_COMMON
219 LONGOPT_READ_CAPTURE_COMMON
222 static const char optstring
[] = OPTSTRING
;
225 static void print_no_capture_support_error(void)
227 cmdarg_err("This version of %s was not built with support for capturing packets.", application_flavor_name_proper());
231 void commandline_early_options(int argc
, char *argv
[])
240 bool capture_option_specified
;
244 * In order to have the -X opts assigned before the wslua machine starts
245 * we need to call getopt_long before epan_init() gets called.
247 * In addition, we process "console only" parameters (ones where we
248 * send output to the console and exit) here, so we don't start GUI
249 * if we're only showing command-line help or version information.
251 * XXX - this pre-scan is done before we start GUI, so we haven't
252 * run "GUI init function" on the arguments. That means that GUI-specific
253 * arguments have not been removed from the argument list; those arguments
254 * begin with "--", and will be treated as an error by getopt_long().
256 * We thus ignore errors - *and* set "ws_opterr" to 0 to suppress the
259 * In order to handle, for example, -o options, we also need to call it
260 * *after* epan_init() gets called, so that the dissectors have had a
261 * chance to register their preferences, so we have another getopt_long()
264 * XXX - can we do this all with one getopt_long() call, saving the
265 * arguments we can't handle until after initializing libwireshark,
266 * and then process them after initializing libwireshark?
268 * Note that we don't want to initialize libwireshark until after the
269 * GUI is up, as that can take a while, and we want a window of some
270 * sort up to show progress while that's happening.
275 capture_option_specified
= false;
277 while ((opt
= ws_getopt_long(argc
, argv
, optstring
, long_options
, NULL
)) != -1) {
279 case 'C': /* Configuration Profile */
280 if (profile_exists (ws_optarg
, false)) {
281 set_profile_name (ws_optarg
);
282 } else if (profile_exists (ws_optarg
, true)) {
283 char *pf_dir_path
, *pf_dir_path2
, *pf_filename
;
284 /* Copy from global profile */
285 if (create_persconffile_profile(ws_optarg
, &pf_dir_path
) == -1) {
286 cmdarg_err("Can't create directory\n\"%s\":\n%s.",
287 pf_dir_path
, g_strerror(errno
));
290 exit(WS_EXIT_INVALID_FILE
);
292 if (copy_persconffile_profile(ws_optarg
, ws_optarg
, true, &pf_filename
,
293 &pf_dir_path
, &pf_dir_path2
) == -1) {
294 cmdarg_err("Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
295 pf_filename
, pf_dir_path2
, pf_dir_path
, g_strerror(errno
));
299 g_free(pf_dir_path2
);
300 exit(WS_EXIT_INVALID_FILE
);
302 set_profile_name (ws_optarg
);
304 cmdarg_err("Configuration Profile \"%s\" does not exist", ws_optarg
);
308 case 'D': /* Print a list of capture devices and exit */
310 exit_status
= EXIT_SUCCESS
;
311 if_list
= capture_interface_list(&err
, &err_str
, NULL
);
314 * An error occurred when fetching the local
315 * interfaces. Report it.
320 cmdarg_err("%s", err_str
);
322 exit_status
= WS_EXIT_PCAP_ERROR
;
324 if (if_list
== NULL
) {
326 * No interfaces were found. If that's not the
327 * result of an error when fetching the local
328 * interfaces, let the user know.
331 cmdarg_err("There are no interfaces on which a capture can be done");
332 exit_status
= WS_EXIT_NO_INTERFACES
;
339 capture_opts_print_interfaces(if_list
);
340 free_interface_list(if_list
);
345 #else /* HAVE_LIBPCAP */
346 capture_option_specified
= true;
347 #endif /* HAVE_LIBPCAP */
349 case 'h': /* Print help and exit */
350 commandline_print_usage(true);
355 if (strcmp(ws_optarg
, "-") == 0)
356 set_stdin_capture(true);
359 case 'P': /* Personal file directory path settings - change these before the Preferences and alike are processed */
360 if (!persfilepath_opt(opt
, ws_optarg
)) {
361 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", ws_optarg
);
365 case 'v': /* Show version and exit */
377 * Extension command line options have to be processed before
378 * we call epan_init() as they are supposed to be used by dissectors
379 * or taps very early in the registration process.
381 ex_opt_add(ws_optarg
);
383 case '?': /* Ignore errors - the "real" scan will catch them. */
389 if (ex_opt_count("lua_script") > 0) {
390 cmdarg_err("This version of %s was not built with support for Lua scripting.", application_flavor_name_proper());
396 if (capture_option_specified
) {
397 print_no_capture_support_error();
398 commandline_print_usage(false);
404 void commandline_override_prefs(int argc
, char *argv
[], bool opt_reset
)
409 * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1.
411 * Ignore errors and keep ws_opterr as 0; error messages will be printed
412 * later by command_other_options()
420 /* Initialize with default values */
421 global_commandline_info
.user_opts
= NULL
;
423 while ((opt
= ws_getopt_long(argc
, argv
, optstring
, long_options
, NULL
)) != -1) {
425 case 'o': /* Override preference from command line */
429 switch (prefs_set_pref(ws_optarg
, &errmsg
)) {
431 global_commandline_info
.user_opts
=
432 g_slist_prepend(global_commandline_info
.user_opts
,
433 g_strdup(ws_optarg
));
435 case PREFS_SET_SYNTAX_ERR
:
436 cmdarg_err("Invalid -o flag \"%s\"%s%s", ws_optarg
,
437 errmsg
? ": " : "", errmsg
? errmsg
: "");
441 case PREFS_SET_NO_SUCH_PREF
:
442 /* not a preference, might be a recent setting */
443 switch (recent_set_arg(ws_optarg
)) {
446 case PREFS_SET_SYNTAX_ERR
:
447 /* shouldn't happen, checked already above */
448 cmdarg_err("Invalid -o flag \"%s\"", ws_optarg
);
451 case PREFS_SET_NO_SUCH_PREF
:
452 case PREFS_SET_OBSOLETE
:
453 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
458 ws_assert_not_reached();
461 case PREFS_SET_OBSOLETE
:
462 /* obsolete preference, might be a recent setting */
463 if (recent_set_arg(ws_optarg
) != PREFS_SET_OK
) {
464 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
470 ws_assert_not_reached();
475 case '?': /* Ignore errors - the "real" scan will catch them. */
480 /* Since we prepended each option when processing `-o`, reverse the list
481 * in case the order of options becomes meaningful.
483 global_commandline_info
.user_opts
= g_slist_reverse(global_commandline_info
.user_opts
);
487 void commandline_other_options(int argc
, char *argv
[], bool opt_reset
)
490 bool arg_error
= false;
492 const char *list_option_supplied
= NULL
;
495 bool capture_option_specified
;
499 * To reset the options parser, set ws_optreset to 1 and set ws_optind to 1.
501 * Also reset ws_opterr to 1, so that error messages are printed by
504 * XXX - if we want to control all the command-line option errors, so
505 * that we can display them where we choose (e.g., in a window), we'd
506 * want to leave ws_opterr as 0, and produce our own messages using ws_optopt.
507 * We'd have to check the value of ws_optopt to see if it's a valid option
508 * letter, in which case *presumably* the error is "this option requires
509 * an argument but none was specified", or not a valid option letter,
510 * in which case *presumably* the error is "this option isn't valid".
511 * Some versions of getopt() let you supply a option string beginning
512 * with ':', which means that getopt() will return ':' rather than '?'
513 * for "this option requires an argument but none was specified", but
514 * not all do. But we're now using getopt_long() - what does it do?
522 /* Initialize with default values */
523 global_commandline_info
.jump_backwards
= SD_FORWARD
;
524 global_commandline_info
.go_to_packet
= 0;
525 global_commandline_info
.jfilter
= NULL
;
526 global_commandline_info
.cf_name
= NULL
;
527 global_commandline_info
.rfilter
= NULL
;
528 global_commandline_info
.dfilter
= NULL
;
530 global_commandline_info
.start_capture
= false;
531 global_commandline_info
.list_link_layer_types
= false;
532 global_commandline_info
.list_timestamp_types
= false;
533 global_commandline_info
.quit_after_cap
= getenv("WIRESHARK_QUIT_AFTER_CAPTURE") ? true : false;
534 global_commandline_info
.capture_comments
= NULL
;
536 global_commandline_info
.full_screen
= false;
538 while ((opt
= ws_getopt_long(argc
, argv
, optstring
, long_options
, NULL
)) != -1) {
540 /*** capture option specific ***/
541 case 'a': /* autostop criteria */
542 case 'b': /* Ringbuffer option */
543 case 'c': /* Capture xxx packets */
544 case 'f': /* capture filter */
545 case 'F': /* capture file type */
546 case 'H': /* Hide capture info dialog box */
547 case 'p': /* Don't capture in promiscuous mode */
548 case 'i': /* Use interface x */
549 case LONGOPT_SET_TSTAMP_TYPE
: /* Set capture timestamp type */
550 case LONGOPT_CAPTURE_TMPDIR
: /* capture temp directory */
551 case LONGOPT_UPDATE_INTERVAL
: /* sync pipe update interval */
552 #ifdef HAVE_PCAP_CREATE
553 case 'I': /* Capture in monitor mode, if available */
555 #ifdef HAVE_PCAP_REMOTE
556 case 'A': /* Authentication */
558 case 's': /* Set the snapshot (capture) length */
559 case 'S': /* "Sync" mode: used for following file ala tail -f */
560 case 'w': /* Write to capture file xxx */
561 case 'y': /* Set the pcap data link type */
562 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
563 case 'B': /* Buffer size */
566 status
= capture_opts_add_opt(&global_capture_opts
, opt
, ws_optarg
);
568 exit_application(status
);
571 capture_option_specified
= true;
576 /*** all non capture option specific ***/
578 /* Configuration profile settings were already processed just ignore them this time*/
580 case 'j': /* Search backwards for a matching packet from filter in option J */
581 global_commandline_info
.jump_backwards
= SD_BACKWARD
;
583 case 'g': /* Go to packet with the given packet number */
584 global_commandline_info
.go_to_packet
= get_nonzero_uint32(ws_optarg
, "go to packet");
586 case 'J': /* Jump to the first packet which matches the filter criteria */
587 global_commandline_info
.jfilter
= ws_optarg
;
589 case 'k': /* Start capture immediately */
591 global_commandline_info
.start_capture
= true;
593 capture_option_specified
= true;
597 case 'l': /* Automatic scrolling in live capture mode */
599 recent
.capture_auto_scroll
= true;
601 capture_option_specified
= true;
605 case 'L': /* Print list of link-layer types and exit */
607 global_commandline_info
.list_link_layer_types
= true;
608 list_option_supplied
= "-L";
610 capture_option_specified
= true;
614 case LONGOPT_LIST_TSTAMP_TYPES
:
616 global_commandline_info
.list_timestamp_types
= true;
617 list_option_supplied
= "--list-time-stamp-types";
619 capture_option_specified
= true;
623 case 'o': /* Override preference from command line */
624 /* Pref overrides were already processed just ignore them this time*/
627 /* Path settings were already processed just ignore them this time*/
629 case 'r': /* Read capture file xxx */
630 /* We may set "last_open_dir" to "cf_name", and if we change
631 "last_open_dir" later, we free the old value, so we have to
632 set "cf_name" to something that's been allocated. */
633 global_commandline_info
.cf_name
= g_strdup(ws_optarg
);
635 case 'R': /* Read file filter */
636 global_commandline_info
.rfilter
= ws_optarg
;
639 /* ext ops were already processed just ignore them this time*/
642 global_commandline_info
.dfilter
= ws_optarg
;
645 /* We won't call the init function for the stat this soon
646 as it would disallow MATE's fields (which are registered
647 by the preferences set callback) from being used as
648 part of a tap filter. Instead, we just add the argument
649 to a list of stat arguments. */
650 if (strcmp("help", ws_optarg
) == 0) {
651 fprintf(stderr
, "%s: The available statistics for the \"-z\" option are:\n", g_get_prgname());
652 list_stat_cmd_args();
655 if (!process_stat_cmd_arg(ws_optarg
)) {
656 cmdarg_err("Invalid -z argument.");
657 cmdarg_err_cont(" -z argument must be one of :");
658 list_stat_cmd_args();
662 case 'd': /* Decode as rule */
663 case 'K': /* Kerberos keytab file */
664 case 'n': /* No name resolution */
665 case 'N': /* Select what types of addresses/port #s to resolve */
666 case 't': /* time stamp type */
667 case 'u': /* Seconds type */
668 case LONGOPT_DISABLE_PROTOCOL
: /* disable dissection of protocol */
669 case LONGOPT_ENABLE_HEURISTIC
: /* enable heuristic dissection of protocol */
670 case LONGOPT_DISABLE_HEURISTIC
: /* disable heuristic dissection of protocol */
671 case LONGOPT_ENABLE_PROTOCOL
: /* enable dissection of protocol (that is disabled by default) */
672 case LONGOPT_ONLY_PROTOCOLS
: /* enable dissection of these comma separated protocols only */
673 case LONGOPT_DISABLE_ALL_PROTOCOLS
: /* disable dissection of all protocols */
674 if (!dissect_opts_handle_opt(opt
, ws_optarg
))
677 case LONGOPT_FULL_SCREEN
:
678 global_commandline_info
.full_screen
= true;
681 case LONGOPT_CAPTURE_COMMENT
: /* capture comment */
682 if (global_commandline_info
.capture_comments
== NULL
) {
683 global_commandline_info
.capture_comments
= g_ptr_array_new_with_free_func(g_free
);
685 g_ptr_array_add(global_commandline_info
.capture_comments
, g_strdup(ws_optarg
));
687 capture_option_specified
= true;
692 case '?': /* Bad flag - print usage message */
702 if (global_commandline_info
.cf_name
!= NULL
) {
704 * Input file name specified with "-r" *and* specified as a regular
705 * command-line argument.
707 cmdarg_err("File name specified both with -r and regular argument");
711 * Input file name not specified with "-r", and a command-line argument
712 * was specified; treat it as the input file name.
714 * Yes, this is different from tshark, where non-flag command-line
715 * arguments are a filter, but this works better on GUI desktops
716 * where a command can be specified to be run to open a particular
717 * file - yes, you could have "-r" as the last part of the command,
718 * but that's a bit ugly.
720 global_commandline_info
.cf_name
= g_strdup(argv
[0]);
728 * Extra command line arguments were specified; complain.
730 cmdarg_err("Invalid argument: %s", argv
[0]);
737 if (ws_optopt
== 'F') {
738 capture_opts_list_file_types();
742 if (capture_option_specified
) {
743 print_no_capture_support_error();
746 commandline_print_usage(false);
751 if (global_commandline_info
.start_capture
&& list_option_supplied
) {
752 /* Specifying *both* is bogus. */
753 cmdarg_err("You can't specify both %s and a live capture.", list_option_supplied
);
757 if (list_option_supplied
) {
758 /* We're supposed to list the link-layer types for an interface;
759 did the user also specify a capture file to be read? */
760 if (global_commandline_info
.cf_name
) {
761 /* Yes - that's bogus. */
762 cmdarg_err("You can't specify %s and a capture file to be read.", list_option_supplied
);
765 /* No - did they specify a ring buffer option? */
766 if (global_capture_opts
.multi_files_on
) {
767 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
771 /* We're supposed to do a live capture; did the user also specify
772 a capture file to be read? */
773 if (global_commandline_info
.start_capture
&& global_commandline_info
.cf_name
) {
774 /* Yes - that's bogus. */
775 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
779 /* No - was the ring buffer option specified and, if so, does it make
781 if (global_capture_opts
.multi_files_on
) {
782 /* Ring buffer works only under certain conditions:
783 a) ring buffer does not work with temporary files;
784 b) real_time_mode and multi_files_on are mutually exclusive -
785 real_time_mode takes precedence;
786 c) it makes no sense to enable the ring buffer if the maximum
787 file size is set to "infinite". */
788 if (global_capture_opts
.save_file
== NULL
) {
789 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
790 global_capture_opts
.multi_files_on
= false;
792 if (!global_capture_opts
.has_autostop_filesize
&&
793 !global_capture_opts
.has_file_duration
&&
794 !global_capture_opts
.has_file_interval
&&
795 !global_capture_opts
.has_file_packets
) {
796 cmdarg_err("Ring buffer requested, but no maximum capture file size, duration, interval or packets were specified.");
797 /* XXX - this must be redesigned as the conditions changed */
804 /* Local function used by commandline_options_drop */
805 static int cl_find_custom(const void *elem_data
, const void *search_data
) {
806 return memcmp(elem_data
, search_data
, strlen((char *)search_data
));
809 /* Drop any options the user specified on the command line with `-o`
810 * that have the given module and preference names
812 void commandline_options_drop(const char *module_name
, const char *pref_name
) {
816 if (global_commandline_info
.user_opts
== NULL
) return;
818 opt_prefix
= ws_strdup_printf("%s.%s:", module_name
, pref_name
);
820 while (NULL
!= (elem
= g_slist_find_custom(global_commandline_info
.user_opts
,
821 (const void *)opt_prefix
, cl_find_custom
))) {
822 global_commandline_info
.user_opts
=
823 g_slist_remove_link(global_commandline_info
.user_opts
, elem
);
825 g_slist_free_1(elem
);
830 /* Reapply any options the user specified on the command line with `-o`
831 * Called in the Qt UI when reloading Lua plugins
832 * For https://gitlab.com/wireshark/wireshark/-/issues/12331
834 void commandline_options_reapply(void) {
836 GSList
*entry
= NULL
;
838 for (entry
= global_commandline_info
.user_opts
; entry
!= NULL
; entry
= g_slist_next(entry
)) {
839 /* Although these options are from the user-supplied command line,
840 * they were checked for validity before we added them to user_opts,
841 * so we don't check them again here. In the worst case, a pref is
842 * specified for a lua plugin which has been edited after Wireshark
843 * started and has had that pref removed; not worth exiting over.
846 prefs_set_pref((char *)entry
->data
, &errmsg
);
847 if (errmsg
!= NULL
) {
854 void commandline_options_apply_extcap(void) {
856 GSList
*entry
= NULL
;
859 if (prefs
.capture_no_extcap
)
862 for (entry
= global_commandline_info
.user_opts
; entry
!= NULL
; entry
= g_slist_next(entry
)) {
863 pref_arg
= (char *)entry
->data
;
864 if (g_str_has_prefix(pref_arg
, "extcap.")) {
865 switch (prefs_set_pref(pref_arg
, &errmsg
)) {
868 case PREFS_SET_SYNTAX_ERR
:
869 cmdarg_err("Invalid -o flag \"%s\"%s%s", pref_arg
,
870 errmsg
? ": " : "", errmsg
? errmsg
: "");
874 case PREFS_SET_NO_SUCH_PREF
:
875 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
879 case PREFS_SET_OBSOLETE
:
880 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
885 ws_assert_not_reached();
891 /* Free memory used to hold user-specified command line options */
892 void commandline_options_free(void) {
893 g_slist_free_full(g_steal_pointer(&global_commandline_info
.user_opts
), g_free
);