Coverage Report

Created: 2026-05-14 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/wsutil/version_info.c
Line
Count
Source
1
/* version_info.c
2
 * Routines to report version information for Wireshark programs
3
 *
4
 * Wireshark - Network traffic analyzer
5
 * By Gerald Combs <gerald@wireshark.org>
6
 * Copyright 1998 Gerald Combs
7
 *
8
 * SPDX-License-Identifier: GPL-2.0-or-later
9
 */
10
11
#include <config.h>
12
#include "version_info.h"
13
14
#include <stdio.h>
15
#include <string.h>
16
#include <locale.h>
17
18
#ifdef _WIN32
19
#include <windows.h>
20
#elif __APPLE__
21
#include <sys/types.h>
22
#include <sys/sysctl.h>
23
#elif __linux__
24
#include <sys/sysinfo.h>
25
#endif
26
27
#include <glib.h>
28
#include <gmodule.h>
29
#include <pcre2.h>
30
31
#ifdef HAVE_XXHASH
32
#include <xxhash.h>
33
#endif
34
35
#ifdef HAVE_ZLIB
36
#include <zlib.h>
37
#endif
38
39
//#ifdef HAVE_ZLIBNG
40
//#include <zlib-ng.h>
41
//#endif
42
43
#include <wsutil/cpu_info.h>
44
#include <wsutil/os_version_info.h>
45
#include <wsutil/crash_info.h>
46
#include <wsutil/plugins.h>
47
48
static char *appname_with_version;
49
static char *copyright_info;
50
static char *license_info;
51
static char *comp_info;
52
static char *runtime_info;
53
54
static void end_string(GString *str);
55
static void get_compiler_info(GString *str);
56
static void get_mem_info(GString *str);
57
58
void
59
ws_init_version_info(const char *appname,
60
    const char* appflavor,
61
    get_version_func version_func,
62
    gather_feature_func gather_compile,
63
    gather_feature_func gather_runtime)
64
15
{
65
15
  GString *comp_info_str, *runtime_info_str;
66
15
  GString *copyright_info_str;
67
15
  GString *license_info_str;
68
69
15
  copyright_info_str = g_string_new(get_copyright_info());
70
15
  end_string(copyright_info_str);
71
15
  copyright_info = g_string_free(copyright_info_str, FALSE);
72
73
15
  license_info_str = g_string_new(get_license_info_short());
74
15
  end_string(license_info_str);
75
15
  license_info = g_string_free(license_info_str, FALSE);
76
77
  /*
78
   * Combine the supplied application name string with the
79
   * version - including the VCS version, for a build from
80
   * a checkout.
81
   */
82
15
  if ((appflavor != NULL) && strstr(appname, appflavor) != NULL) {
83
0
    appname_with_version = ws_strdup_printf("%s %s",
84
0
      appname, version_func());
85
0
  }
86
  /* Include our application flavor. The default is "Wireshark" */
87
15
  else {
88
15
    appname_with_version = ws_strdup_printf("%s (%s) %s",
89
15
      appname, (appflavor != NULL) ? appflavor : "Wireshark", version_func());
90
15
  }
91
92
  /* Get the compile-time version information string */
93
15
  comp_info_str = get_compiled_version_info(gather_compile);
94
95
  /* Get the run-time version information string */
96
15
  runtime_info_str = get_runtime_version_info(gather_runtime);
97
98
15
  comp_info = g_string_free(comp_info_str, FALSE);
99
15
  runtime_info = g_string_free(runtime_info_str, FALSE);
100
101
  /* Add this information to the information to be reported on a crash. */
102
15
  ws_add_crash_info("%s\n"
103
15
    "\n"
104
15
    "%s\n"
105
15
    "%s",
106
15
    appname_with_version, comp_info, runtime_info);
107
15
}
108
109
/*
110
 * Used below in features_to_columns()
111
 */
112
static void
113
rtrim_gstring(GString *str)
114
105
{
115
105
  size_t end = str->len - 1;   // get to 0-based offset
116
810
  while(str->str[end] == ' ') {
117
705
    end--;
118
705
  }
119
105
  end++; // return to 1-based length
120
105
  if (end < str->len) {
121
105
    g_string_truncate(str, end);
122
105
  }
123
105
}
124
125
/*
126
 * Take the list of features, and format it into a number of vertical
127
 * columns, presented in column-major order. Calculates the number of
128
 * columns based on the length of the longest list item.
129
 */
130
static void
131
features_to_columns(feature_list l, GString *str)
132
45
{
133
45
  const uint8_t linelen = 85; // Same value used in end_string() +10
134
45
  const uint8_t linepad = 2;  // left-side padding
135
45
  uint8_t ncols = 0;    // number of columns to show
136
45
  uint8_t maxlen = 0;   // length of longest item
137
45
  unsigned num = 0;   // number of items in list
138
45
  char *c;
139
45
  GPtrArray *a;
140
45
  GList *iter;
141
142
45
  num = g_list_length(*l);
143
45
  if (num == 0) {
144
0
    return;
145
0
  }
146
45
  a = g_ptr_array_sized_new(num);
147
360
  for (iter = *l; iter != NULL; iter = iter->next) {
148
315
    c = (char *)iter->data;
149
315
    maxlen = MAX(maxlen, (uint8_t)strlen(c));
150
315
    g_ptr_array_add(a, iter->data);
151
315
  }
152
45
  maxlen += 2; // allow space between columns
153
45
  ncols = (linelen - linepad) / maxlen;
154
45
  if (ncols <= 1 || num <= 1) {
155
0
    for (iter = *l; iter != NULL; iter = iter->next) {
156
0
      c = (char *)iter->data;
157
0
      g_string_append_printf(str, "%*s%s\n", linepad, "", c);
158
0
    }
159
0
  }
160
45
  else {
161
45
    uint8_t nrows = (num + ncols - 1) / ncols;
162
45
    unsigned i, j;
163
150
    for (i = 0; i < nrows; i++) {
164
105
      g_string_append_printf(str, "%*s", linepad, "");
165
555
      for (j = 0; j < ncols; j++) {
166
450
        unsigned idx = i + (j * nrows);
167
450
        if (idx < num) {
168
315
          g_string_append_printf(str, "%-*s", maxlen, (char *)g_ptr_array_index(a, idx));
169
315
        }
170
450
      }
171
105
      rtrim_gstring(str);
172
105
      g_string_append(str, "\n");
173
105
    }
174
45
  }
175
45
  g_ptr_array_free(a, TRUE);
176
45
}
177
178
/*
179
 * If the string doesn't end with a newline, append one.
180
 * Then word-wrap it to 80 columns.
181
 */
182
static void
183
end_string(GString *str)
184
60
{
185
60
  size_t point;
186
60
  char *p, *q;
187
188
60
  point = str->len;
189
60
  if (point == 0 || str->str[point - 1] != '\n')
190
60
    g_string_append(str, "\n");
191
60
  p = str->str;
192
450
  while (*p != '\0') {
193
390
    q = strchr(p, '\n');
194
390
    if (q - p > 80) {
195
      /*
196
       * Break at or before this point.
197
       */
198
45
      q = p + 80;
199
225
      while (q > p && *q != ' ')
200
180
        q--;
201
45
      if (q != p)
202
45
        *q = '\n';
203
45
    }
204
390
    p = q + 1;
205
390
  }
206
60
}
207
208
const char *
209
get_appname_and_version(void)
210
0
{
211
0
  return appname_with_version;
212
0
}
213
214
void
215
gather_pcre2_compile_info(feature_list l)
216
15
{
217
15
#define PCRE2_DATE_QUOTE(str) #str
218
15
#define PCRE2_DATE_EXPAND_AND_QUOTE(str) PCRE2_DATE_QUOTE(str)
219
  /*
220
   * PCRE2_PRERELEASE appears to be empty for a regular release;
221
   * I don't know what it is for a pre-release.
222
   */
223
15
  with_feature(l, "PCRE2 %u.%u %s", PCRE2_MAJOR, PCRE2_MINOR, PCRE2_DATE_EXPAND_AND_QUOTE(PCRE2_DATE));
224
15
}
225
226
void
227
gather_xxhash_compile_info(feature_list l)
228
15
{
229
#ifdef HAVE_XXHASH
230
  with_feature(l, "xxhash " XXHASH_VERSION_STRING);
231
#else
232
15
  without_feature(l, "xxhash");
233
15
#endif /* HAVE_XXHASH */
234
15
}
235
236
void
237
gather_zlib_compile_info(feature_list l)
238
15
{
239
15
#ifdef HAVE_ZLIB
240
15
#ifdef ZLIB_VERSION
241
15
  with_feature(l, "zlib " ZLIB_VERSION);
242
#else
243
  with_feature(l, "zlib (version unknown)");
244
#endif /* ZLIB_VERSION */
245
#else
246
  without_feature(l, "zlib");
247
#endif /* HAVE_ZLIB */
248
15
}
249
250
void
251
gather_zlib_ng_compile_info(feature_list l)
252
15
{
253
#ifdef HAVE_ZLIBNG
254
  with_feature(l, "zlib-ng " ZLIBNG_VERSION_STRING);
255
#else
256
15
  without_feature(l, "zlib-ng");
257
15
#endif /* HAVE_ZLIB */
258
15
}
259
260
261
/*
262
 * Get various library compile-time versions, put them in a GString,
263
 * and return the GString.
264
 */
265
GString *
266
get_compiled_version_info(gather_feature_func gather_compile)
267
15
{
268
15
  GString *str;
269
15
  GList *l = NULL, *with_list = NULL, *without_list = NULL;
270
271
15
  str = g_string_new("Compile-time info:\n");
272
15
  g_string_append_printf(str, " Bit width: %d-bit\n", (int)sizeof(str) * 8);
273
274
  /* Compiler info */
275
15
  g_string_append_printf(str, "  Compiler: ");
276
15
  get_compiler_info(str);
277
278
15
#ifdef GLIB_MAJOR_VERSION
279
15
  g_string_append_printf(str,
280
15
    "      GLib: %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
281
15
    GLIB_MICRO_VERSION);
282
#else
283
  g_string_append(str, "      GLib: version unknown");
284
#endif
285
#ifdef WS_DISABLE_DEBUG
286
  g_string_append(str, ", release build");
287
#endif
288
#ifdef WS_DISABLE_ASSERT
289
  g_string_append(str, ", without assertions");
290
#endif
291
15
  g_string_append(str, "\n");
292
293
15
  if (gather_compile != NULL) {
294
15
    gather_compile(&l);
295
15
  }
296
297
15
  sort_features(&l);
298
15
  separate_features(&l, &with_list, &without_list);
299
15
  free_features(&l);
300
301
15
  if (with_list != NULL) {
302
15
    g_string_append(str, " With:\n");
303
15
    features_to_columns(&with_list, str);
304
15
    free_features(&with_list);
305
15
  }
306
15
  if (without_list != NULL) {
307
15
    g_string_append(str, " Without:\n");
308
15
    features_to_columns(&without_list, str);
309
15
    free_features(&without_list);
310
15
  }
311
312
15
  end_string(str);
313
15
  return str;
314
15
}
315
316
static void
317
get_mem_info(GString *str)
318
15
{
319
15
  int64_t memsize = 0;
320
321
#ifdef _WIN32
322
  MEMORYSTATUSEX statex;
323
324
  statex.dwLength = sizeof (statex);
325
326
  if (GlobalMemoryStatusEx(&statex))
327
    memsize = statex.ullTotalPhys;
328
#elif __APPLE__
329
  size_t len = sizeof(memsize);
330
  sysctlbyname("hw.memsize", &memsize, &len, NULL, 0);
331
#elif __linux__
332
  struct sysinfo info;
333
15
  if (sysinfo(&info) == 0)
334
15
    if (ckd_mul(&memsize, info.totalram, info.mem_unit))
335
0
      memsize = 0;
336
15
#endif
337
338
15
  if (memsize > 0)
339
15
    g_string_append_printf(str, "%" PRId64 " MB of physical memory", memsize/(1024*1024));
340
15
}
341
342
/*
343
 * Get compiler information, and append it to the GString.
344
 */
345
static void
346
get_compiler_info(GString *str)
347
15
{
348
  /*
349
   * See https://sourceforge.net/apps/mediawiki/predef/index.php?title=Compilers
350
   * information on various defined strings.
351
   *
352
   * GCC's __VERSION__ is a nice text string for humans to
353
   * read.  The page at sourceforge.net largely describes
354
   * numeric #defines that encode the version; if the compiler
355
   * doesn't also offer a nice printable string, we try prettifying
356
   * the number somehow.
357
   */
358
  #if defined(_MSC_FULL_VER)
359
    /*
360
     * We check for this first, as Microsoft have a version of their
361
     * compiler that has Clang as the front end and their code generator
362
     * as the back end.
363
     *
364
     * My head asplode.
365
     */
366
367
    /* As of Wireshark 3.0, we support only Visual Studio 2015 (14.x)
368
     * or later.
369
     *
370
     * https://dev.to/yumetodo/list-of-mscver-and-mscfullver-8nd
371
     * has a *large* table of Microsoft product names, VC++ versions,
372
     * _MSC_VER values, and _MSC_FULL_VER values.  All the versions
373
     * we support define _MSC_FULL_VER.  We don't bother trying to
374
     * get the SP/update/version number from the build number, as
375
     * we'd have to keep updating that with every update; there's no
376
     * way to get that information directly from a predefine, and in
377
     * some cases multiple updates/versions have the *same* build
378
     * number (because they didn't update the toolchain).
379
     *
380
     * https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2017
381
     * defines the format of _MSC_VER and _MSC_FULL_VER.  _MSC_FULL_VER
382
     * is a decimal number of the form MMmmBBBBB, where MM is the compiler/
383
     * toolchain major version, mm is the minor version, and BBBBB is the
384
     * build.  We break it down based on that.
385
     */
386
    #define COMPILER_MAJOR_VERSION (_MSC_FULL_VER / 10000000)
387
    #define COMPILER_MINOR_VERSION ((_MSC_FULL_VER % 10000000) / 100000)
388
    #define COMPILER_BUILD_NUMBER (_MSC_FULL_VER % 100000)
389
390
    /*
391
     * From https://web.archive.org/web/20190125151548/https://blogs.msdn.microsoft.com/vcblog/2014/11/17/c111417-features-in-vs-2015-preview/
392
     * Bakersfield: DevDiv's upper management determines the scheduling
393
     * of new major versions.  They also decided to increment the product
394
     * version from 12 (for VS 2013) to 14 (for VS 2015).  However, the
395
     * C++ compiler's version incremented normally, from 18 to 19.
396
     * (It's larger because the C++ compiler predates the "Visual" in
397
     * Visual C++.)
398
     *
399
     * So the product version number is 5 less than the compiler version
400
     * number.
401
     */
402
    #define VCPP_MAJOR_VERSION  (COMPILER_MAJOR_VERSION - 5)
403
404
    #if VCPP_MAJOR_VERSION == 14
405
      /*
406
       * From https://devblogs.microsoft.com/cppblog/side-by-side-minor-version-msvc-toolsets-in-visual-studio-2017/
407
       *
408
       * We've been delivering improvements to Visual Studio 2017 more
409
       * frequently than ever before. Since its first release in March
410
       * we've released four major updates to VS2017 and are currently
411
       * previewing the fifth update, VS2017 version 15.5.
412
       *
413
       * The MSVC toolset in VS2017 is built as a minor version update to
414
       * the VS2015 compiler toolset. This minor version bump indicates
415
       * that the VS2017 MSVC toolset is binary compatible with the VS2015
416
       * MSVC toolset, enabling an easier upgrade for VS2015 users. Even
417
       * though the MSVC compiler toolset in VS2017 delivers many new
418
       * features and conformance improvements it is a minor version,
419
       * compatible update from 14.00 in VS2015 to 14.10 in VS2017.
420
       */
421
      #if COMPILER_MINOR_VERSION < 10
422
        #define VS_VERSION  "2015"
423
      #elif COMPILER_MINOR_VERSION < 20
424
        #define VS_VERSION  "2017"
425
      #elif COMPILER_MINOR_VERSION < 30
426
      #define VS_VERSION  "2019"
427
      #else
428
        #define VS_VERSION  "2022"
429
      #endif
430
    #else
431
      /*
432
       * Add additional checks here, before the #else.
433
       */
434
      #define VS_VERSION  "(unknown)"
435
    #endif /* VCPP_MAJOR_VERSION */
436
437
    /*
438
     * XXX - should we show the raw compiler version number, as is
439
     * shown by "cl /?", which would be %d.%d.%d.%d with
440
     * COMPILER_MAJOR_VERSION, COMPILER_MINOR_VERSION,
441
     * COMPILER_BUILD_NUMBER, and _MSC_BUILD, the last of which is
442
     * "the revision number element of the compiler's version number",
443
     * which I guess is not to be confused with the build number,
444
     * the _BUILD in the name nonwithstanding.
445
     */
446
    g_string_append_printf(str, "Microsoft Visual Studio " VS_VERSION " (VC++ %d.%d, build %d)",
447
      VCPP_MAJOR_VERSION, COMPILER_MINOR_VERSION, COMPILER_BUILD_NUMBER);
448
    #if defined(__clang__)
449
      /*
450
       * See above.
451
       */
452
      g_string_append_printf(str, " clang/C2 %s and -fno-ms-compatibility",
453
        __VERSION__);
454
    #endif
455
  #elif defined(__GNUC__) && defined(__VERSION__)
456
    /*
457
     * Clang and llvm-gcc also define __GNUC__ and __VERSION__;
458
     * distinguish between them.
459
     */
460
15
    #if defined(__clang__)
461
      /* clang */
462
15
      char *version; /* clang's version string has a trailing space. */
463
15
      #if defined(__clang_version__)
464
15
        version = g_strdup(__clang_version__);
465
15
        g_string_append_printf(str, "Clang %s", g_strstrip(version));
466
      #else
467
        version = g_strdup(__VERSION__);
468
        g_string_append_printf(str, "%s", g_strstrip(version));
469
      #endif /* __clang_version__ */
470
15
      g_free(version);
471
    #elif defined(__llvm__)
472
      /* llvm-gcc */
473
      g_string_append_printf(str, "llvm-gcc %s", __VERSION__);
474
    #else
475
      /* boring old GCC */
476
      g_string_append_printf(str, "GCC %s", __VERSION__);
477
    #endif
478
  #elif defined(__HP_aCC)
479
    g_string_append_printf(str, "HP aCC %d", __HP_aCC);
480
  #elif defined(__xlC__)
481
    g_string_append_printf(str, "IBM XL C %d.%d",
482
      (__xlC__ >> 8) & 0xFF, __xlC__ & 0xFF);
483
    #ifdef __IBMC__
484
      if ((__IBMC__ % 10) != 0)
485
        g_string_append_printf(str, " patch %d", __IBMC__ % 10);
486
    #endif /* __IBMC__ */
487
  #elif defined(__INTEL_COMPILER)
488
    g_string_append_printf(str, "Intel C %d.%d",
489
      __INTEL_COMPILER / 100, (__INTEL_COMPILER / 10) % 10);
490
    if ((__INTEL_COMPILER % 10) != 0)
491
      g_string_append_printf(str, " patch %d", __INTEL_COMPILER % 10);
492
    #ifdef __INTEL_COMPILER_BUILD_DATE
493
      g_string_sprinta(str, ", compiler built %04d-%02d-%02d",
494
        __INTEL_COMPILER_BUILD_DATE / 10000,
495
        (__INTEL_COMPILER_BUILD_DATE / 100) % 100,
496
        __INTEL_COMPILER_BUILD_DATE % 100);
497
    #endif /* __INTEL_COMPILER_BUILD_DATE */
498
  #elif defined(__SUNPRO_C)
499
    g_string_append_printf(str, "Sun C %d.%d",
500
      (__SUNPRO_C >> 8) & 0xF, (__SUNPRO_C >> 4) & 0xF);
501
    if ((__SUNPRO_C & 0xF) != 0)
502
      g_string_append_printf(str, " patch %d", __SUNPRO_C & 0xF);
503
  #else
504
    g_string_append(str, "unknown compiler");
505
  #endif
506
15
  g_string_append(str, "\n");
507
15
}
508
509
void
510
gather_pcre2_runtime_info(feature_list l)
511
15
{
512
  /* From pcre2_api(3):
513
   *     The where argument should point to a buffer that is at  least  24  code
514
   *     units  long.  (The  exact  length  required  can  be  found  by calling
515
   *     pcre2_config() with where set to NULL.)
516
   *
517
   * The API should accept a buffer size as additional input. We could opt for a
518
   * stack buffer size greater than 24 but let's just go with the weirdness...
519
   */
520
15
  int size;
521
15
  char *buf_pcre2;
522
523
15
  size = pcre2_config(PCRE2_CONFIG_VERSION, NULL);
524
15
  if (size < 0 || size > 255) {
525
0
    without_feature(l, "PCRE2 (error querying)");
526
0
    return;
527
0
  }
528
15
  buf_pcre2 = g_malloc((size_t)size + 1);
529
15
  pcre2_config(PCRE2_CONFIG_VERSION, buf_pcre2);
530
15
  buf_pcre2[size] = '\0';
531
15
  with_feature(l, "PCRE2 %s", buf_pcre2);
532
15
  g_free(buf_pcre2);
533
15
}
534
535
void
536
gather_xxhash_runtime_info(feature_list l)
537
15
{
538
15
  (void)l;
539
#if defined(HAVE_XXHASH)
540
  with_feature(l, "xxhash %u", XXH_versionNumber());
541
#endif
542
15
}
543
544
void
545
gather_zlib_runtime_info(feature_list l)
546
15
{
547
15
    (void)l;
548
15
#if defined(HAVE_ZLIB) && !defined(_WIN32)
549
15
  with_feature(l, "zlib %s", zlibVersion());
550
15
#endif
551
15
}
552
553
/*
554
 * Get various library run-time versions, and the OS version, and append
555
 * them to the specified GString.
556
 *
557
 * "additional_info" is called at the end to append any additional
558
 * information; this is required in order to, for example, put the
559
 * libcap information at the end of the string, as we currently
560
 * don't use libcap in TShark.
561
 */
562
GString *
563
get_runtime_version_info(gather_feature_func gather_runtime)
564
15
{
565
15
  GString *str;
566
15
  char *lc;
567
15
  GList *l = NULL, *with_list = NULL, *without_list = NULL;
568
569
15
  str = g_string_new("Runtime info:\n      OS: ");
570
15
  get_os_version_info(str);
571
572
  /* CPU Info */
573
15
  g_string_append(str, "\n     CPU: ");
574
15
  get_cpu_info(str);
575
576
  /* Get info about installed memory */
577
15
  g_string_append(str, "\n  Memory: ");
578
15
  get_mem_info(str);
579
580
15
  g_string_append_printf(str, "\n    GLib: %u.%u.%u\n",
581
15
      glib_major_version, glib_minor_version, glib_micro_version);
582
  /*
583
   * Display LC_CTYPE as a relevant, portable and sort of representative
584
   * locale configuration without being exceedingly verbose and including
585
   * the whole shebang of categories using LC_ALL.
586
   */
587
15
  if ((lc = setlocale(LC_CTYPE, NULL)) != NULL) {
588
15
    g_string_append_printf(str, "  Locale: LC_TYPE=%s\n", lc);
589
15
  }
590
#ifdef HAVE_PLUGINS
591
  if (g_module_supported()) {
592
    g_string_append_printf(str, " Plugins: supported, %d loaded\n", plugins_get_count());
593
  }
594
  else {
595
    g_string_append(str, " Plugins: not supported by platform\n");
596
  }
597
#else
598
15
  g_string_append(str, " Plugins: disabled at compile time\n");
599
15
#endif
600
601
15
  if (gather_runtime != NULL) {
602
15
    gather_runtime(&l);
603
15
  }
604
605
15
  sort_features(&l);
606
15
  separate_features(&l, &with_list, &without_list);
607
15
  free_features(&l);
608
609
15
  if (with_list != NULL) {
610
15
    g_string_append(str, " With:\n");
611
15
    features_to_columns(&with_list, str);
612
15
    free_features(&with_list);
613
15
  }
614
15
  if (without_list != NULL) {
615
0
    g_string_append(str, " Without:\n");
616
0
    features_to_columns(&without_list, str);
617
0
    free_features(&without_list);
618
0
  }
619
620
15
  end_string(str);
621
15
  return str;
622
15
}
623
624
void
625
get_ws_version_number(int *major, int *minor, int *micro)
626
0
{
627
0
  if (major)
628
0
    *major = VERSION_MAJOR;
629
0
  if (minor)
630
0
    *minor = VERSION_MINOR;
631
0
  if (micro)
632
0
    *micro = VERSION_MICRO;
633
0
}
634
635
void
636
show_version(void)
637
0
{
638
0
  printf("%s.\n\n"
639
0
    "%s"
640
0
    "%s\n"
641
0
    "%s\n"
642
0
    "%s",
643
0
    appname_with_version,
644
0
    copyright_info,
645
0
    license_info,
646
0
    comp_info,
647
0
    runtime_info);
648
0
}
649
650
void
651
show_help_header(const char *description)
652
0
{
653
0
  printf("%s\n", appname_with_version);
654
0
  if (description) {
655
0
    printf("%s\n", description);
656
0
    printf("See https://www.wireshark.org for more information.\n");
657
0
  }
658
0
}
659
660
/*
661
 * Get copyright information.
662
 */
663
const char *
664
get_copyright_info(void)
665
15
{
666
15
  return
667
15
    "Copyright 1998-2026 Gerald Combs <gerald@wireshark.org> and contributors.";
668
15
}
669
670
const char *
671
get_license_info_short(void)
672
15
{
673
15
  return
674
15
    "Licensed under the terms of the GNU General Public License (version 2 or later). "
675
15
    "This is free software; see the file named COPYING in the distribution. "
676
15
    "There is NO WARRANTY; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.";
677
15
}
678
679
const char *
680
get_license_info(void)
681
0
{
682
0
  return
683
0
    "This program is free software: you can redistribute it and/or modify "
684
0
    "it under the terms of the GNU General Public License as published by "
685
0
    "the Free Software Foundation, either version 2 of the License, or "
686
0
    "(at your option) any later version. This program is distributed in the "
687
0
    "hope that it will be useful, but WITHOUT ANY WARRANTY; without even "
688
0
    "the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. "
689
0
    "See the GNU General Public License for more details.";
690
0
}
691
692
/*
693
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
694
 *
695
 * Local variables:
696
 * c-basic-offset: 8
697
 * tab-width: 8
698
 * indent-tabs-mode: t
699
 * End:
700
 *
701
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
702
 * :indentSize=8:tabSize=8:noTabs=false:
703
 */