nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* ws_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 | * This program is free software; you can redistribute it and/or |
||
9 | * modify it under the terms of the GNU General Public License |
||
10 | * as published by the Free Software Foundation; either version 2 |
||
11 | * of the License, or (at your option) any later version. |
||
12 | * |
||
13 | * This program is distributed in the hope that it will be useful, |
||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
16 | * GNU General Public License for more details. |
||
17 | * |
||
18 | * You should have received a copy of the GNU General Public License |
||
19 | * along with this program; if not, write to the Free Software |
||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
||
21 | */ |
||
22 | |||
23 | #include <config.h> |
||
24 | |||
25 | #include <stdio.h> |
||
26 | #include <stdlib.h> |
||
27 | #include <string.h> |
||
28 | #include <locale.h> |
||
29 | |||
30 | #ifdef _WIN32 |
||
31 | #include <windows.h> |
||
32 | #endif |
||
33 | |||
34 | #include <glib.h> |
||
35 | |||
36 | #ifdef HAVE_ZLIB |
||
37 | #include <zlib.h> |
||
38 | #endif |
||
39 | |||
40 | #include "version.h" |
||
41 | |||
42 | #include "ws_version_info.h" |
||
43 | |||
44 | #include <wsutil/ws_cpuid.h> |
||
45 | #include <wsutil/copyright_info.h> |
||
46 | #include <wsutil/os_version_info.h> |
||
47 | |||
48 | /* |
||
49 | * If the string doesn't end with a newline, append one. |
||
50 | * Then word-wrap it to 80 columns. |
||
51 | */ |
||
52 | static void |
||
53 | end_string(GString *str) |
||
54 | { |
||
55 | size_t point; |
||
56 | char *p, *q; |
||
57 | |||
58 | point = str->len; |
||
59 | if (point == 0 || str->str[point - 1] != '\n') |
||
60 | g_string_append(str, "\n"); |
||
61 | p = str->str; |
||
62 | while (*p != '\0') { |
||
63 | q = strchr(p, '\n'); |
||
64 | if (q - p > 80) { |
||
65 | /* |
||
66 | * Break at or before this point. |
||
67 | */ |
||
68 | q = p + 80; |
||
69 | while (q > p && *q != ' ') |
||
70 | q--; |
||
71 | if (q != p) |
||
72 | *q = '\n'; |
||
73 | } |
||
74 | p = q + 1; |
||
75 | } |
||
76 | } |
||
77 | |||
78 | static const gchar * |
||
79 | get_zlib_compiled_version_info(void) |
||
80 | { |
||
81 | #ifdef HAVE_ZLIB |
||
82 | #ifdef ZLIB_VERSION |
||
83 | return "with zlib "ZLIB_VERSION; |
||
84 | #else |
||
85 | return "with zlib (version unknown)"; |
||
86 | #endif /* ZLIB_VERSION */ |
||
87 | #else |
||
88 | return "without zlib"; |
||
89 | #endif /* HAVE_ZLIB */ |
||
90 | } |
||
91 | |||
92 | /* |
||
93 | * Get various library compile-time versions, put them in a GString, |
||
94 | * and return the GString. |
||
95 | * |
||
96 | * "prepend_info" is called at the start to prepend any additional |
||
97 | * information before the standard library information. |
||
98 | * |
||
99 | * "append_info" is called at the end to append any additional |
||
100 | * information after the standard library information. This is |
||
101 | * required in order to, for example, put the Portaudio information |
||
102 | * at the end of the string, as we currently don't use Portaudio in |
||
103 | * TShark. |
||
104 | */ |
||
105 | GString * |
||
106 | get_compiled_version_info(void (*prepend_info)(GString *), |
||
107 | void (*append_info)(GString *)) |
||
108 | { |
||
109 | GString *str; |
||
110 | |||
111 | str = g_string_new("Compiled "); |
||
112 | |||
113 | if (sizeof(str) == 4) |
||
114 | g_string_append(str, "(32-bit) "); |
||
115 | else |
||
116 | g_string_append(str, "(64-bit) "); |
||
117 | |||
118 | if (prepend_info) { |
||
119 | (*prepend_info)(str); |
||
120 | g_string_append(str, ", "); |
||
121 | } |
||
122 | |||
123 | /* GLIB */ |
||
124 | g_string_append(str, "with "); |
||
125 | g_string_append_printf(str, |
||
126 | #ifdef GLIB_MAJOR_VERSION |
||
127 | "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, |
||
128 | GLIB_MICRO_VERSION); |
||
129 | #else |
||
130 | "GLib (version unknown)"); |
||
131 | #endif |
||
132 | |||
133 | g_string_append_printf(str, ", %s", get_zlib_compiled_version_info()); |
||
134 | |||
135 | /* Additional application-dependent information */ |
||
136 | if (append_info) |
||
137 | (*append_info)(str); |
||
138 | g_string_append(str, "."); |
||
139 | |||
140 | end_string(str); |
||
141 | |||
142 | return str; |
||
143 | } |
||
144 | |||
145 | /* |
||
146 | * Get the CPU info, and append it to the GString |
||
147 | */ |
||
148 | static void |
||
149 | get_cpu_info(GString *str) |
||
150 | { |
||
151 | guint32 CPUInfo[4]; |
||
152 | char CPUBrandString[0x40]; |
||
153 | unsigned nExIds; |
||
154 | |||
155 | /* http://msdn.microsoft.com/en-us/library/hskdteyh(v=vs.100).aspx */ |
||
156 | |||
157 | /* Calling __cpuid with 0x80000000 as the InfoType argument*/ |
||
158 | /* gets the number of valid extended IDs.*/ |
||
159 | if (!ws_cpuid(CPUInfo, 0x80000000)) |
||
160 | return; |
||
161 | nExIds = CPUInfo[0]; |
||
162 | |||
163 | if( nExIds<0x80000005) |
||
164 | return; |
||
165 | memset(CPUBrandString, 0, sizeof(CPUBrandString)); |
||
166 | |||
167 | /* Interpret CPU brand string.*/ |
||
168 | ws_cpuid(CPUInfo, 0x80000002); |
||
169 | memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo)); |
||
170 | ws_cpuid(CPUInfo, 0x80000003); |
||
171 | memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo)); |
||
172 | ws_cpuid(CPUInfo, 0x80000004); |
||
173 | memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo)); |
||
174 | |||
175 | g_string_append_printf(str, "\n%s", CPUBrandString); |
||
176 | |||
177 | if (ws_cpuid_sse42()) |
||
178 | g_string_append(str, " (with SSE4.2)"); |
||
179 | } |
||
180 | |||
181 | static void |
||
182 | get_mem_info(GString *str _U_) |
||
183 | { |
||
184 | #ifdef _WIN32 |
||
185 | MEMORYSTATUSEX statex; |
||
186 | |||
187 | statex.dwLength = sizeof (statex); |
||
188 | |||
189 | if (GlobalMemoryStatusEx(&statex)) |
||
190 | g_string_append_printf(str, ", with ""%" G_GINT64_MODIFIER "d" "MB of physical memory.\n", statex.ullTotalPhys/(1024*1024)); |
||
191 | #endif |
||
192 | } |
||
193 | |||
194 | /* |
||
195 | * Get compiler information, and append it to the GString. |
||
196 | */ |
||
197 | static void |
||
198 | get_compiler_info(GString *str) |
||
199 | { |
||
200 | /* |
||
201 | * See https://sourceforge.net/apps/mediawiki/predef/index.php?title=Compilers |
||
202 | * information on various defined strings. |
||
203 | * |
||
204 | * GCC's __VERSION__ is a nice text string for humans to |
||
205 | * read. The page at sourceforge.net largely describes |
||
206 | * numeric #defines that encode the version; if the compiler |
||
207 | * doesn't also offer a nice printable string, we try prettifying |
||
208 | * the number somehow. |
||
209 | */ |
||
210 | #if defined(__GNUC__) && defined(__VERSION__) |
||
211 | /* |
||
212 | * Clang and llvm-gcc also define __GNUC__ and __VERSION__; |
||
213 | * distinguish between them. |
||
214 | */ |
||
215 | #if defined(__clang__) |
||
216 | g_string_append_printf(str, "\n\nBuilt using clang %s.\n", __VERSION__); |
||
217 | #elif defined(__llvm__) |
||
218 | g_string_append_printf(str, "\n\nBuilt using llvm-gcc %s.\n", __VERSION__); |
||
219 | #else /* boring old GCC */ |
||
220 | g_string_append_printf(str, "\n\nBuilt using gcc %s.\n", __VERSION__); |
||
221 | #endif /* llvm */ |
||
222 | #elif defined(__HP_aCC) |
||
223 | g_string_append_printf(str, "\n\nBuilt using HP aCC %d.\n", __HP_aCC); |
||
224 | #elif defined(__xlC__) |
||
225 | g_string_append_printf(str, "\n\nBuilt using IBM XL C %d.%d\n", |
||
226 | (__xlC__ >> 8) & 0xFF, __xlC__ & 0xFF); |
||
227 | #ifdef __IBMC__ |
||
228 | if ((__IBMC__ % 10) != 0) |
||
229 | g_string_append_printf(str, " patch %d", __IBMC__ % 10); |
||
230 | #endif /* __IBMC__ */ |
||
231 | g_string_append_printf(str, "\n"); |
||
232 | #elif defined(__INTEL_COMPILER) |
||
233 | g_string_append_printf(str, "\n\nBuilt using Intel C %d.%d", |
||
234 | __INTEL_COMPILER / 100, (__INTEL_COMPILER / 10) % 10); |
||
235 | if ((__INTEL_COMPILER % 10) != 0) |
||
236 | g_string_append_printf(str, " patch %d", __INTEL_COMPILER % 10); |
||
237 | #ifdef __INTEL_COMPILER_BUILD_DATE |
||
238 | g_string_sprinta(str, ", compiler built %04d-%02d-%02d", |
||
239 | __INTEL_COMPILER_BUILD_DATE / 10000, |
||
240 | (__INTEL_COMPILER_BUILD_DATE / 100) % 100, |
||
241 | __INTEL_COMPILER_BUILD_DATE % 100); |
||
242 | #endif /* __INTEL_COMPILER_BUILD_DATE */ |
||
243 | g_string_append_printf(str, "\n"); |
||
244 | #elif defined(_MSC_FULL_VER) |
||
245 | # if _MSC_FULL_VER > 99999999 |
||
246 | /* Quote from the web: |
||
247 | * Bakersfield: DevDiv's upper management determines the scheduling of new major versions. |
||
248 | * They also decided to increment the product version from 12 (for VS 2013) to 14 (for VS 2015). |
||
249 | * However, the C++ compiler's version incremented normally, from 18 to 19. |
||
250 | * (It's larger because the C++ compiler predates the "Visual" in Visual C++.) |
||
251 | * XXX? Should we just output the compiler version? |
||
252 | */ |
||
253 | int compiler_major_version = (_MSC_FULL_VER / 10000000), visual_studio_ver; |
||
254 | |||
255 | if (compiler_major_version < 19) { |
||
256 | visual_studio_ver = compiler_major_version - 6; |
||
257 | }else{ |
||
258 | visual_studio_ver = compiler_major_version - 5; |
||
259 | } |
||
260 | |||
261 | g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d", |
||
262 | visual_studio_ver, |
||
263 | (_MSC_FULL_VER / 100000) % 100); |
||
264 | # if (_MSC_FULL_VER % 100000) != 0 |
||
265 | g_string_append_printf(str, " build %d", |
||
266 | _MSC_FULL_VER % 100000); |
||
267 | # endif |
||
268 | # else |
||
269 | g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d", |
||
270 | (_MSC_FULL_VER / 1000000) - 6, |
||
271 | (_MSC_FULL_VER / 10000) % 100); |
||
272 | # if (_MSC_FULL_VER % 10000) != 0 |
||
273 | g_string_append_printf(str, " build %d", |
||
274 | _MSC_FULL_VER % 10000); |
||
275 | # endif |
||
276 | # endif |
||
277 | g_string_append_printf(str, "\n"); |
||
278 | #elif defined(_MSC_VER) |
||
279 | /* _MSC_FULL_VER not defined, but _MSC_VER defined */ |
||
280 | g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d\n", |
||
281 | (_MSC_VER / 100) - 6, _MSC_VER % 100); |
||
282 | #elif defined(__SUNPRO_C) |
||
283 | g_string_append_printf(str, "\n\nBuilt using Sun C %d.%d", |
||
284 | (__SUNPRO_C >> 8) & 0xF, (__SUNPRO_C >> 4) & 0xF); |
||
285 | if ((__SUNPRO_C & 0xF) != 0) |
||
286 | g_string_append_printf(str, " patch %d", __SUNPRO_C & 0xF); |
||
287 | g_string_append_printf(str, "\n"); |
||
288 | #endif |
||
289 | } |
||
290 | |||
291 | /* XXX - is the setlocale() return string opaque? For glibc the separator is ';' */ |
||
292 | static gchar * |
||
293 | get_locale(void) |
||
294 | { |
||
295 | const gchar *lang; |
||
296 | gchar **locv, *loc; |
||
297 | |||
298 | lang = setlocale(LC_ALL, NULL); |
||
299 | if (lang == NULL) { |
||
300 | return NULL; |
||
301 | } |
||
302 | |||
303 | locv = g_strsplit(lang, ";", -1); |
||
304 | loc = g_strjoinv(", ", locv); |
||
305 | g_strfreev(locv); |
||
306 | return loc; |
||
307 | } |
||
308 | |||
309 | /* |
||
310 | * Get various library run-time versions, and the OS version, and append |
||
311 | * them to the specified GString. |
||
312 | * |
||
313 | * "additional_info" is called at the end to append any additional |
||
314 | * information; this is required in order to, for example, put the |
||
315 | * Portaudio information at the end of the string, as we currently |
||
316 | * don't use Portaudio in TShark. |
||
317 | */ |
||
318 | GString * |
||
319 | get_runtime_version_info(void (*additional_info)(GString *)) |
||
320 | { |
||
321 | GString *str; |
||
322 | gchar *lang; |
||
323 | |||
324 | str = g_string_new("Running on "); |
||
325 | |||
326 | get_os_version_info(str); |
||
327 | |||
328 | /* |
||
329 | * Locale. |
||
330 | * |
||
331 | * This returns the C language's locale information; this |
||
332 | * returns the locale that's actually in effect, even if |
||
333 | * it doesn't happen to match the settings of any of the |
||
334 | * locale environment variables. |
||
335 | * |
||
336 | * XXX - what happens on Windows? If nobody's explicitly |
||
337 | * overridden any of the environment variables, does this |
||
338 | * reflect the locale settings in the OS? If so, does |
||
339 | * that include the code page? (We're not using UTF-16 |
||
340 | * for output to files or the console; using code page |
||
341 | * 65001, i.e. UTF-8, as your system code page probably |
||
342 | * works best with Wireshark.) |
||
343 | */ |
||
344 | if ((lang = get_locale()) != NULL) { |
||
345 | g_string_append_printf(str, ", with locale %s", lang); |
||
346 | g_free(lang); |
||
347 | } |
||
348 | else { |
||
349 | g_string_append(str, ", with default locale"); |
||
350 | } |
||
351 | |||
352 | |||
353 | /* Additional application-dependent information */ |
||
354 | if (additional_info) |
||
355 | (*additional_info)(str); |
||
356 | |||
357 | /* zlib */ |
||
358 | #if defined(HAVE_ZLIB) && !defined(_WIN32) |
||
359 | g_string_append_printf(str, ", with zlib %s", zlibVersion()); |
||
360 | #endif |
||
361 | |||
362 | g_string_append(str, "."); |
||
363 | |||
364 | /* CPU Info */ |
||
365 | get_cpu_info(str); |
||
366 | |||
367 | /* Get info about installed memory Windows only */ |
||
368 | get_mem_info(str); |
||
369 | |||
370 | /* Compiler info */ |
||
371 | get_compiler_info(str); |
||
372 | |||
373 | end_string(str); |
||
374 | |||
375 | return str; |
||
376 | } |
||
377 | |||
378 | void |
||
379 | show_version(const gchar *prog_name_str, GString *comp_info_str, |
||
380 | GString *runtime_info_str) |
||
381 | { |
||
382 | printf("%s %s\n" |
||
383 | "\n" |
||
384 | "%s" |
||
385 | "\n" |
||
386 | "%s" |
||
387 | "\n" |
||
388 | "%s", |
||
389 | prog_name_str, get_ws_vcs_version_info(), get_copyright_info(), |
||
390 | comp_info_str->str, runtime_info_str->str); |
||
391 | } |
||
392 | |||
393 | /* |
||
394 | * Return a version number string for Wireshark, including, for builds |
||
395 | * from a tree checked out from Wireshark's version control system, |
||
396 | * something identifying what version was checked out. |
||
397 | */ |
||
398 | const char * |
||
399 | get_ws_vcs_version_info(void) |
||
400 | { |
||
401 | #ifdef VCSVERSION |
||
402 | return VERSION " (" VCSVERSION ")"; |
||
403 | #else |
||
404 | return VERSION; |
||
405 | #endif |
||
406 | } |
||
407 | |||
408 | /* |
||
409 | * Editor modelines - http://www.wireshark.org/tools/modelines.html |
||
410 | * |
||
411 | * Local variables: |
||
412 | * c-basic-offset: 8 |
||
413 | * tab-width: 8 |
||
414 | * indent-tabs-mode: t |
||
415 | * End: |
||
416 | * |
||
417 | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
||
418 | * :indentSize=8:tabSize=8:noTabs=false: |
||
419 | */ |