Fix Dead Store (Dead assignement/Dead increment) warning found by Clang
[metze/wireshark/wip.git] / version_info.c
1 /* version_info.c
2  * Routines to report version information for stuff used by Wireshark
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 <glib.h>
26
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <errno.h>
31
32 #ifdef HAVE_LIBZ
33 #include <zlib.h>       /* to get the libz version number */
34 #endif
35
36 #ifdef HAVE_SYS_UTSNAME_H
37 #include <sys/utsname.h>
38 #endif
39
40 #include "version_info.h"
41 #include "capture-pcap-util.h"
42 #include <wsutil/unicode-utils.h>
43
44 #include "version.h"
45
46 #ifdef HAVE_WINDOWS_H
47 #include <windows.h>
48 #endif
49
50 #ifdef HAVE_OS_X_FRAMEWORKS
51 #include <CoreFoundation/CoreFoundation.h>
52 #include "cfutils.h"
53 #endif
54
55 #ifdef HAVE_LIBCAP
56 # include <sys/capability.h>
57 #endif
58
59 #ifdef GITVERSION
60         const char *wireshark_gitversion = " (" GITVERSION " from " GITBRANCH ")";
61 #else
62         const char *wireshark_gitversion = "";
63 #endif
64
65 /*
66  * If the string doesn't end with a newline, append one.
67  * Then word-wrap it to 80 columns.
68  */
69 static void
70 end_string(GString *str)
71 {
72         size_t point;
73         char *p, *q;
74
75         point = str->len;
76         if (point == 0 || str->str[point - 1] != '\n')
77                 g_string_append(str, "\n");
78         p = str->str;
79         while (*p != '\0') {
80                 q = strchr(p, '\n');
81                 if (q - p > 80) {
82                         /*
83                          * Break at or before this point.
84                          */
85                         q = p + 80;
86                         while (q > p && *q != ' ')
87                                 q--;
88                         if (q != p)
89                                 *q = '\n';
90                 }
91                 p = q + 1;
92         }
93 }
94
95 /*
96  * Get various library compile-time versions and append them to
97  * the specified GString.
98  *
99  * "additional_info" is called at the end to append any additional
100  * information; this is required in order to, for example, put the
101  * Portaudio information at the end of the string, as we currently
102  * don't use Portaudio in TShark.
103  */
104 void
105 get_compiled_version_info(GString *str, void (*prepend_info)(GString *),
106                           void (*append_info)(GString *))
107 {
108         if (sizeof(str) == 4)
109                 g_string_append(str, "(32-bit) ");
110         else
111                 g_string_append(str, "(64-bit) ");
112
113         if (prepend_info)
114                 (*prepend_info)(str);
115
116         /* GLIB */
117         g_string_append(str, "with ");
118         g_string_append_printf(str,
119 #ifdef GLIB_MAJOR_VERSION
120             "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
121             GLIB_MICRO_VERSION);
122 #else
123             "GLib (version unknown)");
124 #endif
125
126         /* Libpcap */
127         g_string_append(str, ", ");
128         get_compiled_pcap_version(str);
129
130         /* LIBZ */
131         g_string_append(str, ", ");
132 #ifdef HAVE_LIBZ
133         g_string_append(str, "with libz ");
134 #ifdef ZLIB_VERSION
135         g_string_append(str, ZLIB_VERSION);
136 #else /* ZLIB_VERSION */
137         g_string_append(str, "(version unknown)");
138 #endif /* ZLIB_VERSION */
139 #else /* HAVE_LIBZ */
140         g_string_append(str, "without libz");
141 #endif /* HAVE_LIBZ */
142
143 #ifndef _WIN32
144         /* This is UN*X-only. */
145         /* LIBCAP */
146         g_string_append(str, ", ");
147 #ifdef HAVE_LIBCAP
148         g_string_append(str, "with POSIX capabilities");
149 #ifdef _LINUX_CAPABILITY_VERSION
150         g_string_append(str, " (Linux)");
151 #endif /* _LINUX_CAPABILITY_VERSION */
152 #else /* HAVE_LIBCAP */
153         g_string_append(str, "without POSIX capabilities");
154 #endif /* HAVE_LIBCAP */
155 #endif /* _WIN32 */
156
157 #ifdef __linux__
158         /* This is a Linux-specific library. */
159         /* LIBNL */
160         g_string_append(str, ", ");
161 #if defined(HAVE_LIBNL1)
162         g_string_append(str, "with libnl 1");
163 #elif defined(HAVE_LIBNL2)
164         g_string_append(str, "with libnl 2");
165 #elif defined(HAVE_LIBNL3)
166         g_string_append(str, "with libnl 3");
167 #else /* no libnl */
168         g_string_append(str, "without libnl");
169 #endif /* libnl version */
170 #endif /* __linux__ */
171
172         /* Additional application-dependent information */
173         if (append_info)
174                 (*append_info)(str);
175         g_string_append(str, ".");
176
177         end_string(str);
178 }
179
180 #ifdef _WIN32
181 typedef void (WINAPI *nativesi_func_ptr)(LPSYSTEM_INFO);
182 #endif
183
184 /*
185  * Handles the rather elaborate process of getting OS version information
186  * from OS X (we want the OS X version, not the Darwin version, the latter
187  * being easy to get with uname()).
188  */
189 #ifdef HAVE_OS_X_FRAMEWORKS
190
191 /*
192  * Fetch a string, as a UTF-8 C string, from a dictionary, given a key.
193  */
194 static char *
195 get_string_from_dictionary(CFPropertyListRef dict, CFStringRef key)
196 {
197         CFStringRef cfstring;
198
199         cfstring = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)dict,
200             (const void *)key);
201         if (cfstring == NULL)
202                 return NULL;
203         if (CFGetTypeID(cfstring) != CFStringGetTypeID()) {
204                 /* It isn't a string.  Punt. */
205                 return NULL;
206         }
207         return CFString_to_C_string(cfstring);
208 }
209
210 /*
211  * Get the OS X version information, and append it to the GString.
212  * Return TRUE if we succeed, FALSE if we fail.
213  */
214 static gboolean
215 get_os_x_version_info(GString *str)
216 {
217         static const UInt8 server_version_plist_path[] =
218             "/System/Library/CoreServices/ServerVersion.plist";
219         static const UInt8 system_version_plist_path[] =
220             "/System/Library/CoreServices/SystemVersion.plist";
221         CFURLRef version_plist_file_url;
222         CFReadStreamRef version_plist_stream;
223         CFDictionaryRef version_dict;
224         char *string;
225
226         /*
227          * On OS X, report the OS X version number as the OS, and put
228          * the Darwin information in parentheses.
229          *
230          * Alas, Gestalt() is deprecated in Mountain Lion, so the build
231          * fails if you treat deprecation warnings as fatal.  I don't
232          * know of any replacement API, so we fall back on reading
233          * /System/Library/CoreServices/ServerVersion.plist if it
234          * exists, otherwise /System/Library/CoreServices/SystemVersion.plist,
235          * and using ProductUserVisibleVersion.  We also get the build
236          * version from ProductBuildVersion and the product name from
237          * ProductName.
238          */
239         version_plist_file_url = CFURLCreateFromFileSystemRepresentation(NULL,
240             server_version_plist_path, sizeof server_version_plist_path - 1,
241             false);
242         if (version_plist_file_url == NULL)
243                 return FALSE;
244         version_plist_stream = CFReadStreamCreateWithFile(NULL,
245             version_plist_file_url);
246         CFRelease(version_plist_file_url);
247         if (version_plist_stream == NULL)
248                 return FALSE;
249         if (!CFReadStreamOpen(version_plist_stream)) {
250                 CFRelease(version_plist_stream);
251
252                 /*
253                  * Try SystemVersion.plist.
254                  */
255                 version_plist_file_url = CFURLCreateFromFileSystemRepresentation(NULL,
256                     system_version_plist_path, sizeof system_version_plist_path - 1,
257                     false);
258                 if (version_plist_file_url == NULL)
259                         return FALSE;
260                 version_plist_stream = CFReadStreamCreateWithFile(NULL,
261                     version_plist_file_url);
262                 CFRelease(version_plist_file_url);
263                 if (version_plist_stream == NULL)
264                         return FALSE;
265                 if (!CFReadStreamOpen(version_plist_stream)) {
266                         CFRelease(version_plist_stream);
267                         return FALSE;
268                 }
269         }
270 #ifdef HAVE_CFPROPERTYLISTCREATEWITHSTREAM
271         version_dict = (CFDictionaryRef)CFPropertyListCreateWithStream(NULL,
272             version_plist_stream, 0, kCFPropertyListImmutable,
273             NULL, NULL);
274 #else
275         version_dict = (CFDictionaryRef)CFPropertyListCreateFromStream(NULL,
276             version_plist_stream, 0, kCFPropertyListImmutable,
277             NULL, NULL);
278 #endif
279         if (version_dict == NULL) {
280                 CFRelease(version_plist_stream);
281                 return FALSE;
282         }
283         if (CFGetTypeID(version_dict) != CFDictionaryGetTypeID()) {
284                 /* This is *supposed* to be a dictionary.  Punt. */
285                 CFRelease(version_dict);
286                 CFReadStreamClose(version_plist_stream);
287                 CFRelease(version_plist_stream);
288                 return FALSE;
289         }
290         /* Get the product name string. */
291         string = get_string_from_dictionary(version_dict,
292             CFSTR("ProductName"));
293         if (string == NULL) {
294                 CFRelease(version_dict);
295                 CFReadStreamClose(version_plist_stream);
296                 CFRelease(version_plist_stream);
297                 return FALSE;
298         }
299         g_string_append_printf(str, "%s", string);
300         g_free(string);
301
302         /* Get the OS version string. */
303         string = get_string_from_dictionary(version_dict,
304             CFSTR("ProductUserVisibleVersion"));
305         if (string == NULL) {
306                 CFRelease(version_dict);
307                 CFReadStreamClose(version_plist_stream);
308                 CFRelease(version_plist_stream);
309                 return FALSE;
310         }
311         g_string_append_printf(str, " %s", string);
312         g_free(string);
313
314         /* Get the build string */
315         string = get_string_from_dictionary(version_dict,
316             CFSTR("ProductBuildVersion"));
317         if (string == NULL) {
318                 CFRelease(version_dict);
319                 CFReadStreamClose(version_plist_stream);
320                 CFRelease(version_plist_stream);
321                 return FALSE;
322         }
323         g_string_append_printf(str, ", build %s", string);
324         g_free(string);
325         CFRelease(version_dict);
326         CFReadStreamClose(version_plist_stream);
327         CFRelease(version_plist_stream);
328         return TRUE;
329 }
330 #endif
331
332 /*
333  * Get the OS version, and append it to the GString
334  */
335 void get_os_version_info(GString *str)
336 {
337 #if defined(_WIN32)
338         OSVERSIONINFOEX info;
339         SYSTEM_INFO system_info;
340         nativesi_func_ptr nativesi_func;
341 #elif defined(HAVE_SYS_UTSNAME_H)
342         struct utsname name;
343 #endif
344
345 #if defined(_WIN32)
346         /*
347          * See
348          *
349          *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getting_the_system_version.asp
350          *
351          * for more than you ever wanted to know about determining the
352          * flavor of Windows on which you're running.  Implementing more
353          * of that is left as an exercise to the reader - who should
354          * check any copyright information about code samples on MSDN
355          * before cutting and pasting into Wireshark.
356          *
357          * They should also note that you need an OSVERSIONINFOEX structure
358          * to get some of that information, and that not only is that
359          * structure not supported on older versions of Windows, you might
360          * not even be able to compile code that *uses* that structure with
361          * older versions of the SDK.
362          */
363
364         memset(&info, '\0', sizeof info);
365         info.dwOSVersionInfoSize = sizeof info;
366         if (!GetVersionEx((OSVERSIONINFO *)&info)) {
367                 /*
368                  * XXX - get the failure reason.
369                  */
370                 g_string_append(str, "unknown Windows version");
371                 return;
372         }
373
374         memset(&system_info, '\0', sizeof system_info);
375         /* Look for and use the GetNativeSystemInfo() function if available to get the correct processor
376          * architecture even when running 32-bit Wireshark in WOW64 (x86 emulation on 64-bit Windows) */
377         nativesi_func = (nativesi_func_ptr)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "GetNativeSystemInfo");
378         if(nativesi_func)
379                 nativesi_func(&system_info);
380         else
381                 GetSystemInfo(&system_info);
382
383         switch (info.dwPlatformId) {
384
385         case VER_PLATFORM_WIN32s:
386                 /* Shyeah, right. */
387                 g_string_append_printf(str, "Windows 3.1 with Win32s");
388                 break;
389
390         case VER_PLATFORM_WIN32_WINDOWS:
391                 /* Windows OT */
392                 switch (info.dwMajorVersion) {
393
394                 case 4:
395                         /* 3 cheers for Microsoft marketing! */
396                         switch (info.dwMinorVersion) {
397
398                         case 0:
399                                 g_string_append_printf(str, "Windows 95");
400                                 break;
401
402                         case 10:
403                                 g_string_append_printf(str, "Windows 98");
404                                 break;
405
406                         case 90:
407                                 g_string_append_printf(str, "Windows Me");
408                                 break;
409
410                         default:
411                                 g_string_append_printf(str, "Windows OT, unknown version %lu.%lu",
412                                     info.dwMajorVersion, info.dwMinorVersion);
413                                 break;
414                         }
415                         break;
416
417                 default:
418                         g_string_append_printf(str, "Windows OT, unknown version %lu.%lu",
419                             info.dwMajorVersion, info.dwMinorVersion);
420                         break;
421                 }
422                 break;
423
424         case VER_PLATFORM_WIN32_NT:
425                 /* Windows NT */
426                 switch (info.dwMajorVersion) {
427
428                 case 3:
429                 case 4:
430                         g_string_append_printf(str, "Windows NT %lu.%lu",
431                             info.dwMajorVersion, info.dwMinorVersion);
432                         break;
433
434                 case 5:
435                         /* 3 cheers for Microsoft marketing! */
436                         switch (info.dwMinorVersion) {
437
438                         case 0:
439                                 g_string_append_printf(str, "Windows 2000");
440                                 break;
441
442                         case 1:
443                                 g_string_append_printf(str, "Windows XP");
444                                 break;
445
446                         case 2:
447                                 if ((info.wProductType == VER_NT_WORKSTATION) &&
448                                     (system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)) {
449                                         g_string_append_printf(str, "Windows XP Professional x64 Edition");
450                                 } else {
451                                         g_string_append_printf(str, "Windows Server 2003");
452                                         if (system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
453                                                 g_string_append_printf(str, " x64 Edition");
454                                 }
455                                 break;
456
457                         default:
458                                 g_string_append_printf(str, "Windows NT, unknown version %lu.%lu",
459                                                        info.dwMajorVersion, info.dwMinorVersion);
460                                 break;
461                         }
462                         break;
463
464                 case 6: {
465                         gboolean is_nt_workstation;
466
467                         if (system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
468                                 g_string_append(str, "64-bit ");
469                         else if (system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
470                                 g_string_append(str, "32-bit ");
471 #ifndef VER_NT_WORKSTATION
472 #define VER_NT_WORKSTATION 0x01
473                         is_nt_workstation = ((info.wReserved[1] & 0xff) == VER_NT_WORKSTATION);
474 #else
475                         is_nt_workstation = (info.wProductType == VER_NT_WORKSTATION);
476 #endif
477                         switch (info.dwMinorVersion) {
478                         case 0:
479                                 g_string_append_printf(str, is_nt_workstation ? "Windows Vista" : "Windows Server 2008");
480                                 break;
481                         case 1:
482                                 g_string_append_printf(str, is_nt_workstation ? "Windows 7" : "Windows Server 2008 R2");
483                                 break;
484                         case 2:
485                                 g_string_append_printf(str, is_nt_workstation ? "Windows 8" : "Windows Server 2012");
486                                 break;
487                         case 3:
488                                 g_string_append_printf(str, is_nt_workstation ? "Windows 8.1" : "Windows Server 2012 R2");
489                                 break;
490                         default:
491                                 g_string_append_printf(str, "Windows NT, unknown version %lu.%lu",
492                                                        info.dwMajorVersion, info.dwMinorVersion);
493                                 break;
494                         }
495                         break;
496                 }  /* case 6 */
497                 default:
498                         g_string_append_printf(str, "Windows NT, unknown version %lu.%lu",
499                             info.dwMajorVersion, info.dwMinorVersion);
500                         break;
501                 } /* info.dwMajorVersion */
502                 break;
503
504         default:
505                 g_string_append_printf(str, "Unknown Windows platform %lu version %lu.%lu",
506                     info.dwPlatformId, info.dwMajorVersion, info.dwMinorVersion);
507                 break;
508         }
509         if (info.szCSDVersion[0] != '\0')
510                 g_string_append_printf(str, " %s", utf_16to8(info.szCSDVersion));
511         g_string_append_printf(str, ", build %lu", info.dwBuildNumber);
512 #elif defined(HAVE_SYS_UTSNAME_H)
513         /*
514          * We have <sys/utsname.h>, so we assume we have "uname()".
515          */
516         if (uname(&name) < 0) {
517                 g_string_append_printf(str, "unknown OS version (uname failed - %s)",
518                     g_strerror(errno));
519                 return;
520         }
521
522         if (strcmp(name.sysname, "AIX") == 0) {
523                 /*
524                  * Yay, IBM!  Thanks for doing something different
525                  * from most of the other UNIXes out there, and
526                  * making "name.version" apparently be the major
527                  * version number and "name.release" be the minor
528                  * version number.
529                  */
530                 g_string_append_printf(str, "%s %s.%s", name.sysname, name.version,
531                     name.release);
532         } else {
533                 /*
534                  * XXX - get "version" on any other platforms?
535                  *
536                  * On Digital/Tru64 UNIX, it's something unknown.
537                  * On Solaris, it's some kind of build information.
538                  * On HP-UX, it appears to be some sort of subrevision
539                  * thing.
540                  * On *BSD and Darwin/OS X, it's a long string giving
541                  * a build date, config file name, etc., etc., etc..
542                  */
543 #ifdef HAVE_OS_X_FRAMEWORKS
544                 /*
545                  * On Mac OS X, report the Mac OS X version number as
546                  * the OS version if we can, and put the Darwin information
547                  * in parentheses.
548                  */
549                 if (get_os_x_version_info(str)) {
550                         /* Success - append the Darwin information. */
551                         g_string_append_printf(str, " (%s %s)", name.sysname, name.release);
552                 } else {
553                         /* Failure - just use the Darwin information. */
554                         g_string_append_printf(str, "%s %s", name.sysname, name.release);
555                 }
556 #else /* HAVE_OS_X_FRAMEWORKS */
557                 /*
558                  * XXX - on Linux, are there any APIs to get the distribution
559                  * name and version number?  I think some distributions have
560                  * that.
561                  *
562                  * At least on Linux Standard Base-compliant distributions,
563                  * there's an "lsb_release" command.  However:
564                  *
565                  *      http://forums.fedoraforum.org/showthread.php?t=220885
566                  *
567                  * seems to suggest that if you don't have the redhat-lsb
568                  * package installed, you don't have lsb_release, and that
569                  * /etc/fedora-release has the release information on
570                  * Fedora.
571                  *
572                  *      http://linux.die.net/man/1/lsb_release
573                  *
574                  * suggests that there's an /etc/distrib-release file, but
575                  * it doesn't indicate whether "distrib" is literally
576                  * "distrib" or is the name for the distribution, and
577                  * also speaks of an /etc/debian_version file.
578                  *
579                  * "lsb_release" apparently parses /etc/lsb-release, which
580                  * has shell-style assignments, assigning to, among other
581                  * values, DISTRIB_ID (distributor/distribution name),
582                  * DISTRIB_RELEASE (release number of the distribution),
583                  * DISTRIB_DESCRIPTION (*might* be name followed by version,
584                  * but the manpage for lsb_release seems to indicate that's
585                  * not guaranteed), and DISTRIB_CODENAME (code name, e.g.
586                  * "licentious" for the Ubuntu Licentious Lemur release).
587                  * the lsb_release man page also speaks of the distrib-release
588                  * file, but Debian doesn't have one, and Ubuntu 7's
589                  * lsb_release command doesn't look for one.
590                  *
591                  * I've seen references to /etc/redhat-release as well.
592                  *
593                  * At least on my Ubuntu 7 system, /etc/debian_version
594                  * doesn't contain anything interesting (just some Debian
595                  * codenames).
596                  *
597                  * See also
598                  *
599                  *      http://bugs.python.org/issue1322
600                  *
601                  *      http://www.novell.com/coolsolutions/feature/11251.html
602                  *
603                  *      http://linuxmafia.com/faq/Admin/release-files.html
604                  *
605                  * and the Lib/Platform.py file in recent Python 2.x
606                  * releases.
607                  */
608                 g_string_append_printf(str, "%s %s", name.sysname, name.release);
609 #endif /* HAVE_OS_X_FRAMEWORKS */
610         }
611 #else
612         g_string_append(str, "an unknown OS");
613 #endif
614 }
615
616
617 /*
618  * Get the CPU info, and append it to the GString
619  */
620
621 #if defined(_MSC_VER)
622 static void
623 do_cpuid(int *CPUInfo, guint32 selector){
624         __cpuid(CPUInfo, selector);
625 }
626 #elif defined(__GNUC__)
627 #if defined(__x86_64__)
628 static inline void
629 do_cpuid(guint32 *CPUInfo, int selector)
630 {
631         __asm__ __volatile__("cpuid"
632                                                 : "=a" (CPUInfo[0]),
633                                                         "=b" (CPUInfo[1]),
634                                                         "=c" (CPUInfo[2]),
635                                                         "=d" (CPUInfo[3])
636                                                 : "a"(selector));
637 }
638 #else /* (__i386__) */
639 /* would need a test if older proccesors have the cpuid instruction */
640 static void
641 do_cpuid(guint32 *CPUInfo, int selector _U_){
642         CPUInfo[0] = 0;
643 }
644
645 #endif /* defined(__x86_64__)*/
646 #else /* Other compilers */
647 static void
648 do_cpuid(guint32 *CPUInfo, int selector _U_){
649         CPUInfo[0] = 0;
650 }
651 #endif
652
653 /*
654  * Get CPU info on platforms where the cpuid instruction can be used skip 32 bit versions for GCC
655  *      http://www.intel.com/content/dam/www/public/us/en/documents/application-notes/processor-identification-cpuid-instruction-note.pdf
656  * the get_cpuid() routine will return 0 in CPUInfo[0] if cpuinfo isn't available.
657  */
658
659 static void get_cpu_info(GString *str _U_)
660 {
661 #if defined(_MSC_VER)
662         int CPUInfo[4];
663 #else
664         guint32 CPUInfo[4];
665 #endif
666         char CPUBrandString[0x40];
667         unsigned nExIds;
668
669         /* http://msdn.microsoft.com/en-us/library/hskdteyh(v=vs.100).aspx */
670
671         /* Calling __cpuid with 0x80000000 as the InfoType argument*/
672         /* gets the number of valid extended IDs.*/
673         do_cpuid(CPUInfo, 0x80000000);
674         nExIds = CPUInfo[0];
675
676         if( nExIds<0x80000005)
677                 return;
678         memset(CPUBrandString, 0, sizeof(CPUBrandString));
679
680         /* Interpret CPU brand string.*/
681         do_cpuid(CPUInfo, 0x80000002);
682         memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
683         do_cpuid(CPUInfo, 0x80000003);
684         memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
685         do_cpuid(CPUInfo, 0x80000004);
686         memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
687
688         g_string_append_printf(str, "\n%s", CPUBrandString);
689
690 }
691
692 static void get_mem_info(GString *str _U_)
693 {
694 #if defined(_WIN32)
695         MEMORYSTATUSEX statex;
696
697         statex.dwLength = sizeof (statex);
698
699         if(GlobalMemoryStatusEx (&statex))
700                 g_string_append_printf(str, ", with ""%" G_GINT64_MODIFIER "d" "MB of physical memory.\n", statex.ullTotalPhys/(1024*1024));
701 #endif
702
703 }
704
705 /*
706  * Get various library run-time versions, and the OS version, and append
707  * them to the specified GString.
708  */
709 void
710 get_runtime_version_info(GString *str, void (*additional_info)(GString *))
711 {
712 #ifndef _WIN32
713         gchar *lang;
714 #endif
715
716         g_string_append(str, "on ");
717
718         get_os_version_info(str);
719
720 #ifndef _WIN32
721         /* Locale */
722         if ((lang = getenv ("LANG")) != NULL)
723                 g_string_append_printf(str, ", with locale %s", lang);
724         else
725                 g_string_append(str, ", without locale");
726 #endif
727
728         /* Libpcap */
729         g_string_append(str, ", ");
730         get_runtime_pcap_version(str);
731
732         /* zlib */
733 #if defined(HAVE_LIBZ) && !defined(_WIN32)
734         g_string_append_printf(str, ", with libz %s", zlibVersion());
735 #endif
736
737         /* Additional application-dependent information */
738         if (additional_info)
739                 (*additional_info)(str);
740
741         g_string_append(str, ".");
742
743         /* CPU Info */
744         get_cpu_info(str);
745
746         /* Get info about installed memory Windows only */
747         get_mem_info(str);
748
749         /* Compiler info */
750
751         /*
752          * See https://sourceforge.net/apps/mediawiki/predef/index.php?title=Compilers
753          * information on various defined strings.
754          *
755          * GCC's __VERSION__ is a nice text string for humans to
756          * read.  The page at sourceforge.net largely describes
757          * numeric #defines that encode the version; if the compiler
758          * doesn't also offer a nice printable string, we try prettifying
759          * the number somehow.
760          */
761 #if defined(__GNUC__) && defined(__VERSION__)
762         /*
763          * Clang and llvm-gcc also define __GNUC__ and __VERSION__;
764          * distinguish between them.
765          */
766 #if defined(__clang__)
767         g_string_append_printf(str, "\n\nBuilt using clang %s.\n", __VERSION__);
768 #elif defined(__llvm__)
769         g_string_append_printf(str, "\n\nBuilt using llvm-gcc %s.\n", __VERSION__);
770 #else /* boring old GCC */
771         g_string_append_printf(str, "\n\nBuilt using gcc %s.\n", __VERSION__);
772 #endif /* llvm */
773 #elif defined(__HP_aCC)
774         g_string_append_printf(str, "\n\nBuilt using HP aCC %d.\n", __HP_aCC);
775 #elif defined(__xlC__)
776         g_string_append_printf(str, "\n\nBuilt using IBM XL C %d.%d\n",
777             (__xlC__ >> 8) & 0xFF, __xlC__ & 0xFF);
778 #ifdef __IBMC__
779         if ((__IBMC__ % 10) != 0)
780                 g_string_append_printf(str, " patch %d", __IBMC__ % 10);
781 #endif /* __IBMC__ */
782         g_string_append_printf(str, "\n");
783 #elif defined(__INTEL_COMPILER)
784         g_string_append_printf(str, "\n\nBuilt using Intel C %d.%d",
785             __INTEL_COMPILER / 100, (__INTEL_COMPILER / 10) % 10);
786         if ((__INTEL_COMPILER % 10) != 0)
787                 g_string_append_printf(str, " patch %d", __INTEL_COMPILER % 10);
788 #ifdef __INTEL_COMPILER_BUILD_DATE
789         g_string_sprinta(str, ", compiler built %04d-%02d-%02d",
790             __INTEL_COMPILER_BUILD_DATE / 10000,
791             (__INTEL_COMPILER_BUILD_DATE / 100) % 100,
792             __INTEL_COMPILER_BUILD_DATE % 100);
793 #endif /* __INTEL_COMPILER_BUILD_DATE */
794         g_string_append_printf(str, "\n");
795 #elif defined(_MSC_FULL_VER)
796 # if _MSC_FULL_VER > 99999999
797         g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d",
798                                (_MSC_FULL_VER / 10000000) - 6,
799                                (_MSC_FULL_VER / 100000) % 100);
800 #  if (_MSC_FULL_VER % 100000) != 0
801         g_string_append_printf(str, " build %d",
802                                _MSC_FULL_VER % 100000);
803 #  endif
804 # else
805         g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d",
806                                (_MSC_FULL_VER / 1000000) - 6,
807                                (_MSC_FULL_VER / 10000) % 100);
808 #  if (_MSC_FULL_VER % 10000) != 0
809         g_string_append_printf(str, " build %d",
810                                _MSC_FULL_VER % 10000);
811 #  endif
812 # endif
813         g_string_append_printf(str, "\n");
814 #elif defined(_MSC_VER)
815         /* _MSC_FULL_VER not defined, but _MSC_VER defined */
816         g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d\n",
817             (_MSC_VER / 100) - 6, _MSC_VER % 100);
818 #elif defined(__SUNPRO_C)
819         g_string_append_printf(str, "\n\nBuilt using Sun C %d.%d",
820             (__SUNPRO_C >> 8) & 0xF, (__SUNPRO_C >> 4) & 0xF);
821         if ((__SUNPRO_C & 0xF) != 0)
822                 g_string_append_printf(str, " patch %d", __SUNPRO_C & 0xF);
823         g_string_append_printf(str, "\n");
824 #endif
825
826         end_string(str);
827 }
828
829 /*
830  * Get copyright information.
831  */
832 const char *
833 get_copyright_info(void)
834 {
835         return
836 "Copyright 1998-2014 Gerald Combs <gerald@wireshark.org> and contributors.\n"
837 "This is free software; see the source for copying conditions. There is NO\n"
838 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
839 }
840
841 #if defined(_WIN32)
842 /*
843  * Get the major OS version.
844  */
845 /* XXX - Should this return the minor version as well, e.g. 0x00050002? */
846 guint32
847 get_os_major_version()
848 {
849         OSVERSIONINFO info;
850         info.dwOSVersionInfoSize = sizeof info;
851         if (GetVersionEx(&info)) {
852                 return info.dwMajorVersion;
853         }
854         return 0;
855 }
856 #endif
857
858 /*
859  * Editor modelines
860  *
861  * Local Variables:
862  * c-basic-offset: 8
863  * tab-width: 8
864  * indent-tabs-mode: t
865  * End:
866  *
867  * ex: set shiftwidth=8 tabstop=8 noexpandtab:
868  * :indentSize=8:tabSize=8:noTabs=false:
869  */