Move get_os_version_info() to libwsutil.
[gd/wireshark/.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
31 #ifdef HAVE_LIBZ
32 #include <zlib.h>       /* to get the libz version number */
33 #endif
34
35 #include "version_info.h"
36 #include "capture-pcap-util.h"
37 #include <wsutil/unicode-utils.h>
38 #include <wsutil/ws_cpuid.h>
39 #include <wsutil/os_version_info.h>
40
41 #include "version.h"
42
43 #ifdef HAVE_WINDOWS_H
44 #include <windows.h>
45 #endif
46
47 #ifdef HAVE_LIBCAP
48 # include <sys/capability.h>
49 #endif
50
51 #ifdef GITVERSION
52         const char *wireshark_gitversion = " (" GITVERSION " from " GITBRANCH ")";
53 #else
54         const char *wireshark_gitversion = "";
55 #endif
56
57 /*
58  * If the string doesn't end with a newline, append one.
59  * Then word-wrap it to 80 columns.
60  */
61 static void
62 end_string(GString *str)
63 {
64         size_t point;
65         char *p, *q;
66
67         point = str->len;
68         if (point == 0 || str->str[point - 1] != '\n')
69                 g_string_append(str, "\n");
70         p = str->str;
71         while (*p != '\0') {
72                 q = strchr(p, '\n');
73                 if (q - p > 80) {
74                         /*
75                          * Break at or before this point.
76                          */
77                         q = p + 80;
78                         while (q > p && *q != ' ')
79                                 q--;
80                         if (q != p)
81                                 *q = '\n';
82                 }
83                 p = q + 1;
84         }
85 }
86
87 /*
88  * Get various library compile-time versions and append them to
89  * the specified GString.
90  *
91  * "additional_info" is called at the end to append any additional
92  * information; this is required in order to, for example, put the
93  * Portaudio information at the end of the string, as we currently
94  * don't use Portaudio in TShark.
95  */
96 void
97 get_compiled_version_info(GString *str, void (*prepend_info)(GString *),
98                           void (*append_info)(GString *))
99 {
100         if (sizeof(str) == 4)
101                 g_string_append(str, "(32-bit) ");
102         else
103                 g_string_append(str, "(64-bit) ");
104
105         if (prepend_info)
106                 (*prepend_info)(str);
107
108         /* GLIB */
109         g_string_append(str, "with ");
110         g_string_append_printf(str,
111 #ifdef GLIB_MAJOR_VERSION
112             "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
113             GLIB_MICRO_VERSION);
114 #else
115             "GLib (version unknown)");
116 #endif
117
118         /* Libpcap */
119         g_string_append(str, ", ");
120         get_compiled_pcap_version(str);
121
122         /* LIBZ */
123         g_string_append(str, ", ");
124 #ifdef HAVE_LIBZ
125         g_string_append(str, "with libz ");
126 #ifdef ZLIB_VERSION
127         g_string_append(str, ZLIB_VERSION);
128 #else /* ZLIB_VERSION */
129         g_string_append(str, "(version unknown)");
130 #endif /* ZLIB_VERSION */
131 #else /* HAVE_LIBZ */
132         g_string_append(str, "without libz");
133 #endif /* HAVE_LIBZ */
134
135 #ifndef _WIN32
136         /* This is UN*X-only. */
137         /* LIBCAP */
138         g_string_append(str, ", ");
139 #ifdef HAVE_LIBCAP
140         g_string_append(str, "with POSIX capabilities");
141 #ifdef _LINUX_CAPABILITY_VERSION
142         g_string_append(str, " (Linux)");
143 #endif /* _LINUX_CAPABILITY_VERSION */
144 #else /* HAVE_LIBCAP */
145         g_string_append(str, "without POSIX capabilities");
146 #endif /* HAVE_LIBCAP */
147 #endif /* _WIN32 */
148
149 #ifdef __linux__
150         /* This is a Linux-specific library. */
151         /* LIBNL */
152         g_string_append(str, ", ");
153 #if defined(HAVE_LIBNL1)
154         g_string_append(str, "with libnl 1");
155 #elif defined(HAVE_LIBNL2)
156         g_string_append(str, "with libnl 2");
157 #elif defined(HAVE_LIBNL3)
158         g_string_append(str, "with libnl 3");
159 #else /* no libnl */
160         g_string_append(str, "without libnl");
161 #endif /* libnl version */
162 #endif /* __linux__ */
163
164         /* Additional application-dependent information */
165         if (append_info)
166                 (*append_info)(str);
167         g_string_append(str, ".");
168
169         end_string(str);
170 }
171
172 /*
173  * Get the CPU info, and append it to the GString
174  */
175
176 static void get_cpu_info(GString *str _U_)
177 {
178         guint32 CPUInfo[4];
179         char CPUBrandString[0x40];
180         unsigned nExIds;
181
182         /* http://msdn.microsoft.com/en-us/library/hskdteyh(v=vs.100).aspx */
183
184         /* Calling __cpuid with 0x80000000 as the InfoType argument*/
185         /* gets the number of valid extended IDs.*/
186         if (!ws_cpuid(CPUInfo, 0x80000000))
187                 return;
188         nExIds = CPUInfo[0];
189
190         if( nExIds<0x80000005)
191                 return;
192         memset(CPUBrandString, 0, sizeof(CPUBrandString));
193
194         /* Interpret CPU brand string.*/
195         ws_cpuid(CPUInfo, 0x80000002);
196         memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
197         ws_cpuid(CPUInfo, 0x80000003);
198         memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
199         ws_cpuid(CPUInfo, 0x80000004);
200         memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
201
202         g_string_append_printf(str, "\n%s", CPUBrandString);
203
204         if (ws_cpuid_sse42())
205                 g_string_append(str, " (with SSE4.2)");
206 }
207
208 static void get_mem_info(GString *str _U_)
209 {
210 #if defined(_WIN32)
211         MEMORYSTATUSEX statex;
212
213         statex.dwLength = sizeof (statex);
214
215         if(GlobalMemoryStatusEx (&statex))
216                 g_string_append_printf(str, ", with ""%" G_GINT64_MODIFIER "d" "MB of physical memory.\n", statex.ullTotalPhys/(1024*1024));
217 #endif
218
219 }
220
221 /*
222  * Get various library run-time versions, and the OS version, and append
223  * them to the specified GString.
224  */
225 void
226 get_runtime_version_info(GString *str, void (*additional_info)(GString *))
227 {
228 #ifndef _WIN32
229         gchar *lang;
230 #endif
231
232         g_string_append(str, "on ");
233
234         get_os_version_info(str);
235
236 #ifndef _WIN32
237         /* Locale */
238         if ((lang = getenv ("LANG")) != NULL)
239                 g_string_append_printf(str, ", with locale %s", lang);
240         else
241                 g_string_append(str, ", without locale");
242 #endif
243
244         /* Libpcap */
245         g_string_append(str, ", ");
246         get_runtime_pcap_version(str);
247
248         /* zlib */
249 #if defined(HAVE_LIBZ) && !defined(_WIN32)
250         g_string_append_printf(str, ", with libz %s", zlibVersion());
251 #endif
252
253         /* Additional application-dependent information */
254         if (additional_info)
255                 (*additional_info)(str);
256
257         g_string_append(str, ".");
258
259         /* CPU Info */
260         get_cpu_info(str);
261
262         /* Get info about installed memory Windows only */
263         get_mem_info(str);
264
265         /* Compiler info */
266
267         /*
268          * See https://sourceforge.net/apps/mediawiki/predef/index.php?title=Compilers
269          * information on various defined strings.
270          *
271          * GCC's __VERSION__ is a nice text string for humans to
272          * read.  The page at sourceforge.net largely describes
273          * numeric #defines that encode the version; if the compiler
274          * doesn't also offer a nice printable string, we try prettifying
275          * the number somehow.
276          */
277 #if defined(__GNUC__) && defined(__VERSION__)
278         /*
279          * Clang and llvm-gcc also define __GNUC__ and __VERSION__;
280          * distinguish between them.
281          */
282 #if defined(__clang__)
283         g_string_append_printf(str, "\n\nBuilt using clang %s.\n", __VERSION__);
284 #elif defined(__llvm__)
285         g_string_append_printf(str, "\n\nBuilt using llvm-gcc %s.\n", __VERSION__);
286 #else /* boring old GCC */
287         g_string_append_printf(str, "\n\nBuilt using gcc %s.\n", __VERSION__);
288 #endif /* llvm */
289 #elif defined(__HP_aCC)
290         g_string_append_printf(str, "\n\nBuilt using HP aCC %d.\n", __HP_aCC);
291 #elif defined(__xlC__)
292         g_string_append_printf(str, "\n\nBuilt using IBM XL C %d.%d\n",
293             (__xlC__ >> 8) & 0xFF, __xlC__ & 0xFF);
294 #ifdef __IBMC__
295         if ((__IBMC__ % 10) != 0)
296                 g_string_append_printf(str, " patch %d", __IBMC__ % 10);
297 #endif /* __IBMC__ */
298         g_string_append_printf(str, "\n");
299 #elif defined(__INTEL_COMPILER)
300         g_string_append_printf(str, "\n\nBuilt using Intel C %d.%d",
301             __INTEL_COMPILER / 100, (__INTEL_COMPILER / 10) % 10);
302         if ((__INTEL_COMPILER % 10) != 0)
303                 g_string_append_printf(str, " patch %d", __INTEL_COMPILER % 10);
304 #ifdef __INTEL_COMPILER_BUILD_DATE
305         g_string_sprinta(str, ", compiler built %04d-%02d-%02d",
306             __INTEL_COMPILER_BUILD_DATE / 10000,
307             (__INTEL_COMPILER_BUILD_DATE / 100) % 100,
308             __INTEL_COMPILER_BUILD_DATE % 100);
309 #endif /* __INTEL_COMPILER_BUILD_DATE */
310         g_string_append_printf(str, "\n");
311 #elif defined(_MSC_FULL_VER)
312 # if _MSC_FULL_VER > 99999999
313         g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d",
314                                (_MSC_FULL_VER / 10000000) - 6,
315                                (_MSC_FULL_VER / 100000) % 100);
316 #  if (_MSC_FULL_VER % 100000) != 0
317         g_string_append_printf(str, " build %d",
318                                _MSC_FULL_VER % 100000);
319 #  endif
320 # else
321         g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d",
322                                (_MSC_FULL_VER / 1000000) - 6,
323                                (_MSC_FULL_VER / 10000) % 100);
324 #  if (_MSC_FULL_VER % 10000) != 0
325         g_string_append_printf(str, " build %d",
326                                _MSC_FULL_VER % 10000);
327 #  endif
328 # endif
329         g_string_append_printf(str, "\n");
330 #elif defined(_MSC_VER)
331         /* _MSC_FULL_VER not defined, but _MSC_VER defined */
332         g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d\n",
333             (_MSC_VER / 100) - 6, _MSC_VER % 100);
334 #elif defined(__SUNPRO_C)
335         g_string_append_printf(str, "\n\nBuilt using Sun C %d.%d",
336             (__SUNPRO_C >> 8) & 0xF, (__SUNPRO_C >> 4) & 0xF);
337         if ((__SUNPRO_C & 0xF) != 0)
338                 g_string_append_printf(str, " patch %d", __SUNPRO_C & 0xF);
339         g_string_append_printf(str, "\n");
340 #endif
341
342         end_string(str);
343 }
344
345 #if defined(_WIN32)
346 /*
347  * Get the major OS version.
348  */
349 /* XXX - Should this return the minor version as well, e.g. 0x00050002? */
350 guint32
351 get_os_major_version()
352 {
353         OSVERSIONINFO info;
354         info.dwOSVersionInfoSize = sizeof info;
355         if (GetVersionEx(&info)) {
356                 return info.dwMajorVersion;
357         }
358         return 0;
359 }
360 #endif
361
362 /*
363  * Editor modelines
364  *
365  * Local Variables:
366  * c-basic-offset: 8
367  * tab-width: 8
368  * indent-tabs-mode: t
369  * End:
370  *
371  * ex: set shiftwidth=8 tabstop=8 noexpandtab:
372  * :indentSize=8:tabSize=8:noTabs=false:
373  */