2 * Routines to report version information for Wireshark programs
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
21 #include <sys/types.h>
22 #include <sys/sysctl.h>
24 #include <sys/sysinfo.h>
35 #include "version_info.h"
37 #include <wsutil/cpu_info.h>
38 #include <wsutil/copyright_info.h>
39 #include <wsutil/os_version_info.h>
40 #include <wsutil/ws_printf.h> /* ws_debug_printf */
41 #include <wsutil/plugins.h>
44 * If the string doesn't end with a newline, append one.
45 * Then word-wrap it to 80 columns.
48 end_string(GString *str)
54 if (point == 0 || str->str[point - 1] != '\n')
55 g_string_append(str, "\n");
61 * Break at or before this point.
64 while (q > p && *q != ' ')
74 get_zlib_compiled_version_info(void)
78 return "with zlib "ZLIB_VERSION;
80 return "with zlib (version unknown)";
81 #endif /* ZLIB_VERSION */
83 return "without zlib";
84 #endif /* HAVE_ZLIB */
88 * Get various library compile-time versions, put them in a GString,
89 * and return the GString.
91 * "prepend_info" is called at the start to prepend any additional
92 * information before the standard library information.
94 * "append_info" is called at the end to append any additional
95 * information after the standard library information. This is
96 * required in order to, for example, put Qt information at the
97 * end of the string, as we don't use Qt in TShark.
100 get_compiled_version_info(void (*prepend_info)(GString *),
101 void (*append_info)(GString *))
105 str = g_string_new("Compiled ");
107 if (sizeof(str) == 4)
108 g_string_append(str, "(32-bit) ");
110 g_string_append(str, "(64-bit) ");
113 (*prepend_info)(str);
114 g_string_append(str, ", ");
118 g_string_append(str, "with ");
119 g_string_append_printf(str,
120 #ifdef GLIB_MAJOR_VERSION
121 "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
124 "GLib (version unknown)");
127 g_string_append_printf(str, ", %s", get_zlib_compiled_version_info());
129 /* Additional application-dependent information */
132 g_string_append(str, ".");
140 get_mem_info(GString *str)
145 MEMORYSTATUSEX statex;
147 statex.dwLength = sizeof (statex);
149 if (GlobalMemoryStatusEx(&statex))
150 memsize = statex.ullTotalPhys;
152 size_t len = sizeof(memsize);
153 sysctlbyname("hw.memsize", &memsize, &len, NULL, 0);
156 if (sysinfo(&info) == 0)
157 memsize = info.totalram * info.mem_unit;
161 g_string_append_printf(str, ", with ""%" G_GINT64_MODIFIER "d" " MB of physical memory", memsize/(1024*1024));
165 * Get compiler information, and append it to the GString.
168 get_compiler_info(GString *str)
171 * See https://sourceforge.net/apps/mediawiki/predef/index.php?title=Compilers
172 * information on various defined strings.
174 * GCC's __VERSION__ is a nice text string for humans to
175 * read. The page at sourceforge.net largely describes
176 * numeric #defines that encode the version; if the compiler
177 * doesn't also offer a nice printable string, we try prettifying
178 * the number somehow.
180 #if defined(__GNUC__) && defined(__VERSION__)
182 * Clang and llvm-gcc also define __GNUC__ and __VERSION__;
183 * distinguish between them.
185 #if defined(__clang__)
187 * Microsoft have a version of their compiler that has Clang
188 * as the front end and their code generator as the back end.
192 #if defined(__MSC_VER)
193 g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d.%d clang/C2 %s and -fno-ms-compatibility.\n",
194 (_MSC_VER / 100) - 6, _MSC_VER % 100, __VERSION__);
196 g_string_append_printf(str, "\n\nBuilt using clang %s.\n", __VERSION__);
197 #endif /* defined(__MSC_VER) */
198 #elif defined(__llvm__)
199 g_string_append_printf(str, "\n\nBuilt using llvm-gcc %s.\n", __VERSION__);
200 #else /* boring old GCC */
201 g_string_append_printf(str, "\n\nBuilt using gcc %s.\n", __VERSION__);
203 #elif defined(__HP_aCC)
204 g_string_append_printf(str, "\n\nBuilt using HP aCC %d.\n", __HP_aCC);
205 #elif defined(__xlC__)
206 g_string_append_printf(str, "\n\nBuilt using IBM XL C %d.%d\n",
207 (__xlC__ >> 8) & 0xFF, __xlC__ & 0xFF);
209 if ((__IBMC__ % 10) != 0)
210 g_string_append_printf(str, " patch %d", __IBMC__ % 10);
211 #endif /* __IBMC__ */
212 g_string_append_printf(str, "\n");
213 #elif defined(__INTEL_COMPILER)
214 g_string_append_printf(str, "\n\nBuilt using Intel C %d.%d",
215 __INTEL_COMPILER / 100, (__INTEL_COMPILER / 10) % 10);
216 if ((__INTEL_COMPILER % 10) != 0)
217 g_string_append_printf(str, " patch %d", __INTEL_COMPILER % 10);
218 #ifdef __INTEL_COMPILER_BUILD_DATE
219 g_string_sprinta(str, ", compiler built %04d-%02d-%02d",
220 __INTEL_COMPILER_BUILD_DATE / 10000,
221 (__INTEL_COMPILER_BUILD_DATE / 100) % 100,
222 __INTEL_COMPILER_BUILD_DATE % 100);
223 #endif /* __INTEL_COMPILER_BUILD_DATE */
224 g_string_append_printf(str, "\n");
225 #elif defined(_MSC_FULL_VER)
226 # if _MSC_FULL_VER > 99999999
227 /* Quote from the web:
228 * Bakersfield: DevDiv's upper management determines the scheduling of new major versions.
229 * They also decided to increment the product version from 12 (for VS 2013) to 14 (for VS 2015).
230 * However, the C++ compiler's version incremented normally, from 18 to 19.
231 * (It's larger because the C++ compiler predates the "Visual" in Visual C++.)
232 * XXX? Should we just output the compiler version?
234 int compiler_major_version = (_MSC_FULL_VER / 10000000), visual_studio_ver;
236 if (compiler_major_version < 19) {
237 visual_studio_ver = compiler_major_version - 6;
239 visual_studio_ver = compiler_major_version - 5;
242 g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d",
244 (_MSC_FULL_VER / 100000) % 100);
245 # if (_MSC_FULL_VER % 100000) != 0
246 g_string_append_printf(str, " build %d",
247 _MSC_FULL_VER % 100000);
250 g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d",
251 (_MSC_FULL_VER / 1000000) - 6,
252 (_MSC_FULL_VER / 10000) % 100);
253 # if (_MSC_FULL_VER % 10000) != 0
254 g_string_append_printf(str, " build %d",
255 _MSC_FULL_VER % 10000);
258 g_string_append_printf(str, "\n");
259 #elif defined(_MSC_VER)
260 /* _MSC_FULL_VER not defined, but _MSC_VER defined */
261 #if defined(__clang__)
262 /* More head asplosion; see above. */
263 g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d.%d clang/C2 %s.\n",
264 (_MSC_VER / 100) - 6, _MSC_VER % 100, __VERSION__);
266 g_string_append_printf(str, "\n\nBuilt using clang %s.\n", __VERSION__);
267 #endif /* defined(__MSC_VER) */
268 g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d\n",
269 (_MSC_VER / 100) - 6, _MSC_VER % 100);
270 #elif defined(__SUNPRO_C)
271 g_string_append_printf(str, "\n\nBuilt using Sun C %d.%d",
272 (__SUNPRO_C >> 8) & 0xF, (__SUNPRO_C >> 4) & 0xF);
273 if ((__SUNPRO_C & 0xF) != 0)
274 g_string_append_printf(str, " patch %d", __SUNPRO_C & 0xF);
275 g_string_append_printf(str, "\n");
279 /* XXX - is the setlocale() return string opaque? For glibc the separator is ';' */
286 lang = setlocale(LC_ALL, NULL);
291 locv = g_strsplit(lang, ";", -1);
292 loc = g_strjoinv(", ", locv);
298 * Get various library run-time versions, and the OS version, and append
299 * them to the specified GString.
301 * "additional_info" is called at the end to append any additional
302 * information; this is required in order to, for example, put the
303 * libcap information at the end of the string, as we currently
304 * don't use libcap in TShark.
307 get_runtime_version_info(void (*additional_info)(GString *))
312 str = g_string_new("Running on ");
314 get_os_version_info(str);
319 /* Get info about installed memory */
325 * This returns the C language's locale information; this
326 * returns the locale that's actually in effect, even if
327 * it doesn't happen to match the settings of any of the
328 * locale environment variables.
330 * On Windows get_locale returns the full language, country
331 * name, and code page, e.g. "English_United States.1252":
332 * https://msdn.microsoft.com/en-us/library/x99tb11d.aspx
334 if ((lang = get_locale()) != NULL) {
335 g_string_append_printf(str, ", with locale %s", lang);
339 g_string_append(str, ", with default locale");
343 /* Additional application-dependent information */
345 (*additional_info)(str);
348 #if defined(HAVE_ZLIB) && !defined(_WIN32)
349 g_string_append_printf(str, ", with zlib %s", zlibVersion());
354 if (g_module_supported()) {
355 g_string_append_printf(str, ", binary plugins supported (%d loaded)", plugins_get_count());
358 g_string_append(str, ", binary plugins not supported");
362 g_string_append(str, ".");
365 get_compiler_info(str);
373 show_version(const gchar *prog_name_str, GString *comp_info_str,
374 GString *runtime_info_str)
376 ws_debug_printf("%s %s\n"
383 prog_name_str, get_ws_vcs_version_info(), get_copyright_info(),
384 comp_info_str->str, runtime_info_str->str);
388 * Return a version number string for Wireshark, including, for builds
389 * from a tree checked out from Wireshark's version control system,
390 * something identifying what version was checked out.
393 get_ws_vcs_version_info(void)
396 return VERSION " (" VCSVERSION ")";
403 get_ws_version_number(int *major, int *minor, int *micro)
406 *major = VERSION_MAJOR;
408 *minor = VERSION_MINOR;
410 *micro = VERSION_MICRO;
414 * Editor modelines - http://www.wireshark.org/tools/modelines.html
419 * indent-tabs-mode: t
422 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
423 * :indentSize=8:tabSize=8:noTabs=false: