Reinsert #ifdef's removed by mistake.
[obnox/wireshark/wip.git] / version_info.c
1 /* version_info.c
2  * Routines to report version information for stuff used by Wireshark
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_PYTHON
30 #include <Python.h> /* to get the Python version number (PY_VERSION) */
31 #endif
32
33 #include <glib.h>
34
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <errno.h>
39
40 #ifdef HAVE_LIBZ
41 #include <zlib.h>       /* to get the libz version number */
42 #endif
43
44 #ifdef HAVE_LIBPCRE
45 #include <pcre.h>       /* to get the libpcre version number */
46 #endif /* HAVE_LIBPCRE */
47
48 #ifdef HAVE_SYS_UTSNAME_H
49 #include <sys/utsname.h>
50 #endif
51
52 #include "version_info.h"
53 #include "capture-pcap-util.h"
54 #include <wsutil/unicode-utils.h>
55
56 #include "svnversion.h"
57
58 #ifdef HAVE_WINDOWS_H
59 #include <windows.h>
60 #endif
61
62 #ifdef HAVE_OS_X_FRAMEWORKS
63 #include <CoreServices/CoreServices.h>
64 #endif
65
66 #ifdef HAVE_LIBCAP
67 # include <sys/capability.h>
68 #endif
69
70 #ifdef HAVE_GEOIP
71 #include <epan/geoip_db.h>
72 #endif
73
74 #ifdef SVNVERSION
75         const char *wireshark_svnversion = " (" SVNVERSION " from " SVNPATH ")";
76 #else
77         const char *wireshark_svnversion = "";
78 #endif
79
80 /*
81  * If the string doesn't end with a newline, append one.
82  * Then word-wrap it to 80 columns.
83  */
84 static void
85 end_string(GString *str)
86 {
87         size_t point;
88         char *p, *q;
89
90         point = str->len;
91         if (point == 0 || str->str[point - 1] != '\n')
92                 g_string_append(str, "\n");
93         p = str->str;
94         while (*p != '\0') {
95                 q = strchr(p, '\n');
96                 if (q - p > 80) {
97                         /*
98                          * Break at or before this point.
99                          */
100                         q = p + 80;
101                         while (q > p && *q != ' ')
102                                 q--;
103                         if (q != p)
104                                 *q = '\n';
105                 }
106                 p = q + 1;
107         }
108 }
109
110 /*
111  * Get various library compile-time versions and append them to
112  * the specified GString.
113  *
114  * "additional_info" is called at the end to append any additional
115  * information; this is required in order to, for example, put the
116  * Portaudio information at the end of the string, as we currently
117  * don't use Portaudio in TShark.
118  */
119 void
120 get_compiled_version_info(GString *str, void (*additional_info)(GString *))
121 {
122         if (sizeof(str) == 4)
123                 g_string_append(str, "(32-bit) ");
124         else
125                 g_string_append(str, "(64-bit) ");
126
127         /* GLIB */
128         g_string_append(str, "with ");
129         g_string_append_printf(str,
130 #ifdef GLIB_MAJOR_VERSION
131             "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
132             GLIB_MICRO_VERSION);
133 #else
134             "GLib (version unknown)");
135 #endif
136
137         /* Libpcap */
138         g_string_append(str, ", ");
139         get_compiled_pcap_version(str);
140
141         /* LIBZ */
142         g_string_append(str, ", ");
143 #ifdef HAVE_LIBZ
144         g_string_append(str, "with libz ");
145 #ifdef ZLIB_VERSION
146         g_string_append(str, ZLIB_VERSION);
147 #else /* ZLIB_VERSION */
148         g_string_append(str, "(version unknown)");
149 #endif /* ZLIB_VERSION */
150 #else /* HAVE_LIBZ */
151         g_string_append(str, "without libz");
152 #endif /* HAVE_LIBZ */
153
154         /* LIBCAP */
155         g_string_append(str, ", ");
156 #ifdef HAVE_LIBCAP
157         g_string_append(str, "with POSIX capabilities");
158 #ifdef _LINUX_CAPABILITY_VERSION
159         g_string_append(str, " (Linux)");
160 #endif /* _LINUX_CAPABILITY_VERSION */
161 #else /* HAVE_LIBCAP */
162         g_string_append(str, "without POSIX capabilities");
163 #endif /* HAVE_LIBCAP */
164
165         /* Additional application-dependent information */
166         if (additional_info)
167                 (*additional_info)(str);
168         g_string_append(str, ".");
169
170 #if !defined(HAVE_LIBPCRE) && !GLIB_CHECK_VERSION(2,14,0)
171         g_string_append(str,
172         "\nNOTE: this build doesn't support the \"matches\" operator for Wireshark filter syntax");
173         g_string_append(str, ".");
174 #endif  /* HAVE_LIBPCRE */
175
176         end_string(str);
177 }
178
179 /*
180  * Get various library run-time versions, and the OS version, and append
181  * them to the specified GString.
182  */
183 void
184 get_runtime_version_info(GString *str, void (*additional_info)(GString *))
185 {
186 #if defined(_WIN32)
187         OSVERSIONINFOEX info;
188         SYSTEM_INFO system_info;
189 #elif defined(HAVE_SYS_UTSNAME_H)
190         struct utsname name;
191 #endif
192 #if HAVE_OS_X_FRAMEWORKS
193         SInt32 macosx_ver, macosx_major_ver, macosx_minor_ver, macosx_bugfix_ver;
194 #endif
195
196         g_string_append(str, "on ");
197
198 #if defined(_WIN32)
199         /*
200          * See
201          *
202          *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getting_the_system_version.asp
203          *
204          * for more than you ever wanted to know about determining the
205          * flavor of Windows on which you're running.  Implementing more
206          * of that is left as an exercise to the reader - who should
207          * check any copyright information about code samples on MSDN
208          * before cutting and pasting into Wireshark.
209          *
210          * They should also note that you need an OSVERSIONINFOEX structure
211          * to get some of that information, and that not only is that
212          * structure not supported on older versions of Windows, you might
213          * not even be able to compile code that *uses* that structure with
214          * older versions of the SDK.
215          */
216
217         memset(&info, '\0', sizeof info);
218         info.dwOSVersionInfoSize = sizeof info;
219         if (!GetVersionEx((OSVERSIONINFO *)&info)) {
220                 /*
221                  * XXX - get the failure reason.
222                  */
223                 g_string_append(str, "unknown Windows version");
224                 return;
225         }
226
227         memset(&system_info, '\0', sizeof system_info);
228         GetSystemInfo(&system_info);    /* only for W2K or greater .... (which is what we support) */
229
230         switch (info.dwPlatformId) {
231
232         case VER_PLATFORM_WIN32s:
233                 /* Shyeah, right. */
234                 g_string_append_printf(str, "Windows 3.1 with Win32s");
235                 break;
236
237         case VER_PLATFORM_WIN32_WINDOWS:
238                 /* Windows OT */
239                 switch (info.dwMajorVersion) {
240
241                 case 4:
242                         /* 3 cheers for Microsoft marketing! */
243                         switch (info.dwMinorVersion) {
244
245                         case 0:
246                                 g_string_append_printf(str, "Windows 95");
247                                 break;
248
249                         case 10:
250                                 g_string_append_printf(str, "Windows 98");
251                                 break;
252
253                         case 90:
254                                 g_string_append_printf(str, "Windows Me");
255                                 break;
256
257                         default:
258                                 g_string_append_printf(str, "Windows OT, unknown version %lu.%lu",
259                                     info.dwMajorVersion, info.dwMinorVersion);
260                                 break;
261                         }
262                         break;
263
264                 default:
265                         g_string_append_printf(str, "Windows OT, unknown version %lu.%lu",
266                             info.dwMajorVersion, info.dwMinorVersion);
267                         break;
268                 }
269                 break;
270
271         case VER_PLATFORM_WIN32_NT:
272                 /* Windows NT */
273                 switch (info.dwMajorVersion) {
274
275                 case 3:
276                 case 4:
277                         g_string_append_printf(str, "Windows NT %lu.%lu",
278                             info.dwMajorVersion, info.dwMinorVersion);
279                         break;
280
281                 case 5:
282                         /* 3 cheers for Microsoft marketing! */
283                         switch (info.dwMinorVersion) {
284
285                         case 0:
286                                 g_string_append_printf(str, "Windows 2000");
287                                 break;
288
289                         case 1:
290                                 g_string_append_printf(str, "Windows XP");
291                                 break;
292
293                         case 2:
294                                 if ((info.wProductType == VER_NT_WORKSTATION) &&
295                                     (system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)) {
296                                         g_string_append_printf(str, "Windows XP Professional x64 Edition");
297                                 } else {
298                                         g_string_append_printf(str, "Windows Server 2003");
299                                         if (system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
300                                                 g_string_append_printf(str, " x64 Edition");
301                                 }
302                                 break;
303
304                         default:
305                                 g_string_append_printf(str, "Windows NT, unknown version %lu.%lu",
306                                                        info.dwMajorVersion, info.dwMinorVersion);
307                                 break;
308                         }
309                         break;
310
311                 case 6: {
312                         gboolean is_nt_workstation;
313
314                         if (system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
315                                 g_string_append(str, "64-bit ");
316                         else if (system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
317                                 g_string_append(str, "32-bit ");
318 #ifndef VER_NT_WORKSTATION
319 #define VER_NT_WORKSTATION 0x01
320                         is_nt_workstation = ((info.wReserved[1] & 0xff) == VER_NT_WORKSTATION);
321 #else
322                         is_nt_workstation = (info.wProductType == VER_NT_WORKSTATION);
323 #endif
324                         switch (info.dwMinorVersion) {
325                         case 0:
326                                 g_string_append_printf(str, is_nt_workstation ? "Windows Vista" : "Windows Server 2008");
327                                 break;
328                         case 1:
329                                 g_string_append_printf(str, is_nt_workstation ? "Windows 7" : "Windows Server 2008 R2");
330                                 break;
331                         default:
332                                 g_string_append_printf(str, "Windows NT, unknown version %lu.%lu",
333                                                        info.dwMajorVersion, info.dwMinorVersion);
334                                 break;
335                         }
336                         break;
337                 }  /* case 6 */
338                 default:
339                         g_string_append_printf(str, "Windows NT, unknown version %lu.%lu",
340                             info.dwMajorVersion, info.dwMinorVersion);
341                         break;
342                 } /* info.dwMajorVersion */
343                 break;
344
345         default:
346                 g_string_append_printf(str, "Unknown Windows platform %lu version %lu.%lu",
347                     info.dwPlatformId, info.dwMajorVersion, info.dwMinorVersion);
348                 break;
349         }
350         if (info.szCSDVersion[0] != '\0')
351                 g_string_append_printf(str, " %s", utf_16to8(info.szCSDVersion));
352         g_string_append_printf(str, ", build %lu", info.dwBuildNumber);
353 #elif defined(HAVE_SYS_UTSNAME_H)
354         /*
355          * We have <sys/utsname.h>, so we assume we have "uname()".
356          */
357         if (uname(&name) < 0) {
358                 g_string_append_printf(str, "unknown OS version (uname failed - %s)",
359                     strerror(errno));
360                 return;
361         }
362
363         if (strcmp(name.sysname, "AIX") == 0) {
364                 /*
365                  * Yay, IBM!  Thanks for doing something different
366                  * from most of the other UNIXes out there, and
367                  * making "name.version" apparently be the major
368                  * version number and "name.release" be the minor
369                  * version number.
370                  */
371                 g_string_append_printf(str, "%s %s.%s", name.sysname, name.version,
372                     name.release);
373         } else {
374                 /*
375                  * XXX - get "version" on any other platforms?
376                  *
377                  * On Digital/Tru64 UNIX, it's something unknown.
378                  * On Solaris, it's some kind of build information.
379                  * On HP-UX, it appears to be some sort of subrevision
380                  * thing.
381                  * On *BSD and Darwin/OS X, it's a long string giving
382                  * a build date, config file name, etc., etc., etc..
383                  */
384 #ifdef HAVE_OS_X_FRAMEWORKS
385                 /*
386                  * On Mac OS X, report the Mac OS X version number as
387                  * the OS, and put the Darwin information in parentheses.
388                  *
389                  * XXX - can we get the build name?  There's no API to
390                  * get it; it's currently in
391                  * /System/Library/CoreServices/SystemVersion.plist
392                  * but there's no guarantee that it will continue to
393                  * be there.
394                  */
395                 Gestalt(gestaltSystemVersion, &macosx_ver);
396
397                 /* The following functions are only available in Mac OS 10.4+ */
398                 if(macosx_ver >= 0x1040) {
399                         Gestalt(gestaltSystemVersionMajor, &macosx_major_ver);
400                         Gestalt(gestaltSystemVersionMinor, &macosx_minor_ver);
401                         Gestalt(gestaltSystemVersionBugFix, &macosx_bugfix_ver);
402
403                         g_string_append_printf(str, "Mac OS %ld.%ld.%ld",
404                                           (long)macosx_major_ver,
405                                           (long)macosx_minor_ver,
406                                           (long)macosx_bugfix_ver);
407                 } else {
408                         g_string_append_printf(str, "Mac OS X < 10.4 [%lx]",
409                                           (long)macosx_ver);
410                         /* See Apple's Gestalt Manager Reference for meanings
411                          * of the macosx_ver values. */
412                 }
413                 g_string_append_printf(str, " (%s %s)", name.sysname, name.release);
414 #else /* HAVE_OS_X_FRAMEWORKS */
415                 /*
416                  * XXX - on Linux, are there any APIs to get the distribution
417                  * name and version number?  I think some distributions have
418                  * that.
419                  *
420                  * At least on Linux Standard Base-compliant distributions,
421                  * there's an "lsb_release" command.  However:
422                  *
423                  *      http://forums.fedoraforum.org/showthread.php?t=220885
424                  *
425                  * seems to suggest that if you don't have the redhat-lsb
426                  * package installed, you don't have lsb_release, and that
427                  * /etc/fedora-release has the release information on
428                  * Fedora.
429                  *
430                  *      http://linux.die.net/man/1/lsb_release
431                  *
432                  * suggests that there's an /etc/distrib-release file, but
433                  * it doesn't indicate whether "distrib" is literally
434                  * "distrib" or is the name for the distribution, and
435                  * also speaks of an /etc/debian_version file.
436                  *
437                  * "lsb_release" apparently parses /etc/lsb-release, which
438                  * has shell-style assignments, assigning to, among other
439                  * values, DISTRIB_ID (distributor/distribution name),
440                  * DISTRIB_RELEASE (release number of the distribution),
441                  * DISTRIB_DESCRIPTION (*might* be name followed by version,
442                  * but the manpage for lsb_release seems to indicate that's
443                  * not guaranteed), and DISTRIB_CODENAME (code name, e.g.
444                  * "licentious" for the Ubuntu Licentious Lemur release).
445                  * the lsb_release man page also speaks of the distrib-release
446                  * file, but Debian doesn't have one, and Ubuntu 7's
447                  * lsb_release command doesn't look for one.
448                  *
449                  * I've seen references to /etc/redhat-release as well.
450                  *
451                  * At least on my Ubuntu 7 system, /etc/debian_version
452                  * doesn't contain anything interesting (just some Debian
453                  * codenames).
454                  *
455                  * See also
456                  *
457                  *      http://bugs.python.org/issue1322
458                  *
459                  *      http://www.novell.com/coolsolutions/feature/11251.html
460                  *
461                  *      http://linuxmafia.com/faq/Admin/release-files.html
462                  *
463                  * and the Lib/Platform.py file in recent Python 2.x
464                  * releases.
465                  */
466                 g_string_append_printf(str, "%s %s", name.sysname, name.release);
467 #endif /* HAVE_OS_X_FRAMEWORKS */
468         }
469 #else
470         g_string_append(str, "an unknown OS");
471 #endif
472
473         /* Libpcap */
474         g_string_append(str, ", ");
475         get_runtime_pcap_version(str);
476
477         /* zlib */
478 #if defined(HAVE_LIBZ) && !defined(_WIN32)
479         g_string_append_printf(str, ", with libz %s", zlibVersion());
480 #endif
481
482         /* Additional application-dependent information */
483         if (additional_info)
484                 (*additional_info)(str);
485
486         g_string_append(str, ".");
487
488         /* Compiler info */
489
490         /*
491          * See http://predef.sourceforge.net/precomp.html for
492          * information on various defined strings.
493          *
494          * GCC's __VERSION__ is a nice text string for humans to
495          * read.  The page at predef.sourceforge.net largely
496          * describes numeric #defines that encode the version;
497          * if the compiler doesn't also offer a nice printable
498          * string, we should probably prettify the number somehow.
499          */
500 #if defined(__GNUC__) && defined(__VERSION__)
501 #if defined(__clang__)
502         g_string_append_printf(str, "\n\nBuilt using clang %s.\n", __VERSION__);
503 #elif defined(__llvm__)
504         g_string_append_printf(str, "\n\nBuilt using llvm-gcc %s.\n", __VERSION__);
505 #else /* boring old GCC */
506         g_string_append_printf(str, "\n\nBuilt using gcc %s.\n", __VERSION__);
507 #endif /* llvm */
508 #elif defined(__HP_aCC)
509         g_string_append_printf(str, "\n\nBuilt using HP aCC %d.\n", __HP_aCC);
510 #elif defined(__xlC__)
511         g_string_append_printf(str, "\n\nBuilt using IBM XL C %d.%d\n",
512             (__xlC__ >> 8) & 0xFF, __xlC__ & 0xFF);
513 #ifdef __IBMC__
514         if ((__IBMC__ % 10) != 0)
515                 g_string_append_printf(str, " patch %d", __IBMC__ % 10);
516 #endif /* __IBMC__ */
517         g_string_append_printf(str, "\n");
518 #elif defined(__INTEL_COMPILER)
519         g_string_append_printf(str, "\n\nBuilt using Intel C %d.%d",
520             __INTEL_COMPILER / 100, (__INTEL_COMPILER / 10) % 10);
521         if ((__INTEL_COMPILER % 10) != 0)
522                 g_string_append_printf(str, " patch %d", __INTEL_COMPILER % 10);
523 #ifdef __INTEL_COMPILER_BUILD_DATE
524         g_string_sprinta(str, ", compiler built %04d-%02d-%02d",
525             __INTEL_COMPILER_BUILD_DATE / 10000,
526             (__INTEL_COMPILER_BUILD_DATE / 100) % 100,
527             __INTEL_COMPILER_BUILD_DATE % 100);
528 #endif /* __INTEL_COMPILER_BUILD_DATE */
529         g_string_append_printf(str, "\n");
530 #elif defined(_MSC_FULL_VER)
531         if (_MSC_FULL_VER > 99999999) {
532                 g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d",
533                     (_MSC_FULL_VER / 10000000) - 6,
534                     (_MSC_FULL_VER / 100000) % 100);
535                 if ((_MSC_FULL_VER % 100000) != 0)
536                         g_string_append_printf(str, " build %d",
537                             _MSC_FULL_VER % 100000);
538         } else {
539                 g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d",
540                     (_MSC_FULL_VER / 1000000) - 6,
541                     (_MSC_FULL_VER / 10000) % 100);
542                 if ((_MSC_FULL_VER % 10000) != 0)
543                         g_string_append_printf(str, " build %d",
544                             _MSC_FULL_VER % 10000);
545         }
546         g_string_append_printf(str, "\n");
547 #elif defined(_MSC_VER)
548         /* _MSC_FULL_VER not defined, but _MSC_VER defined */
549         g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d\n",
550             (_MSC_VER / 100) - 6, _MSC_VER % 100);
551 #elif defined(__SUNPRO_C)
552         g_string_append_printf(str, "\n\nBuilt using Sun C %d.%d",
553             (__SUNPRO_C >> 8) & 0xF, (__SUNPRO_C >> 4) & 0xF);
554         if ((__SUNPRO_C & 0xF) != 0)
555                 g_string_append_printf(str, " patch %d", __SUNPRO_C & 0xF);
556         g_string_append_printf(str, "\n");
557 #endif
558
559         end_string(str);
560 }
561
562 /*
563  * Get copyright information.
564  */
565 const char *
566 get_copyright_info(void)
567 {
568         return
569 "Copyright 1998-2010 Gerald Combs <gerald@wireshark.org> and contributors.\n"
570 "This is free software; see the source for copying conditions. There is NO\n"
571 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
572 }
573
574 #if defined(_WIN32)
575 /*
576  * Get the major OS version.
577  */
578 /* XXX - Should this return the minor version as well, e.g. 0x00050002? */
579 guint32
580 get_os_major_version()
581 {
582         OSVERSIONINFO info;
583         info.dwOSVersionInfoSize = sizeof info;
584         if (GetVersionEx(&info)) {
585                 return info.dwMajorVersion;
586         }
587         return 0;
588 }
589 #endif
590
591 /*
592  * Editor modelines
593  *
594  * Local Variables:
595  * c-basic-offset: 8
596  * tab-width: 8
597  * indent-tabs-mode: t
598  * End:
599  *
600  * ex: set shiftwidth=8 tabstop=8 noexpandtab
601  * :indentSize=8:tabSize=8:noTabs=false:
602  */