Fix a typo in a comment.
[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 #include <glib.h>
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <errno.h>
35
36 #ifdef HAVE_LIBZ
37 #include <zlib.h>       /* to get the libz version number */
38 #endif
39
40 #ifdef HAVE_LIBPCRE
41 #include <pcre.h>       /* to get the libpcre version number */
42 #endif /* HAVE_LIBPCRE */
43
44 #if (defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBGNUTLS)) && defined(_WIN32)
45 #include <winposixtype.h>
46 #endif
47
48 #ifdef HAVE_LIBGCRYPT
49 #include <gcrypt.h>
50 #endif /* HAVE_LIBGCRYPT */
51
52 #ifdef HAVE_LIBGNUTLS
53 #include <gnutls/gnutls.h>
54 #endif /* HAVE_LIBGNUTLS */
55
56 #ifdef HAVE_SYS_UTSNAME_H
57 #include <sys/utsname.h>
58 #endif
59
60 #include "version_info.h"
61 #include "capture-pcap-util.h"
62 #include <wsutil/unicode-utils.h>
63
64 #include "svnversion.h"
65
66 #ifdef HAVE_WINDOWS_H
67 #include <windows.h>
68 #endif
69
70 #ifdef HAVE_C_ARES
71 #include <ares_version.h>
72 #endif
73
74 #ifdef HAVE_LUA_5_1
75 #include <lua.h>
76 #endif
77
78 #ifdef HAVE_LIBSMI
79 #include <smi.h>
80 #endif
81
82 #ifdef HAVE_OS_X_FRAMEWORKS
83 #include <CoreServices/CoreServices.h>
84 #endif
85
86 #ifdef HAVE_LIBCAP
87 # include <sys/capability.h>
88 #endif
89
90 #ifdef SVNVERSION
91         const char *wireshark_svnversion = " (" SVNVERSION ")";
92 #else
93         const char *wireshark_svnversion = "";
94 #endif
95
96 /*
97  * If the string doesn't end with a newline, append one.
98  * Then word-wrap it to 80 columns.
99  */
100 static void
101 end_string(GString *str)
102 {
103         size_t point;
104         char *p, *q;
105
106         point = strlen(str->str);
107         if (point == 0 || str->str[point - 1] != '\n')
108                 g_string_append(str, "\n");
109         p = str->str;
110         while (*p != '\0') {
111                 q = strchr(p, '\n');
112                 if (q - p > 80) {
113                         /*
114                          * Break at or before this point.
115                          */
116                         q = p + 80;
117                         while (q > p && *q != ' ')
118                                 q--;
119                         if (q != p)
120                                 *q = '\n';
121                 }
122                 p = q + 1;
123         }
124 }
125
126 /*
127  * Get various library compile-time versions and append them to
128  * the specified GString.
129  *
130  * "additional_info" is called at the end to append any additional
131  * information; this is required in order to, for example, put the
132  * Portaudio information at the end of the string, as we currently
133  * don't use Portaudio in TShark.
134  */
135 void
136 get_compiled_version_info(GString *str, void (*additional_info)(GString *))
137 {
138         /* GLIB */
139         g_string_append(str, "with ");
140         g_string_append_printf(str,
141 #ifdef GLIB_MAJOR_VERSION
142             "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
143             GLIB_MICRO_VERSION);
144 #else
145             "GLib (version unknown)");
146 #endif
147
148         /* Libpcap */
149         g_string_append(str, ", ");
150         get_compiled_pcap_version(str);
151
152         /* LIBZ */
153         g_string_append(str, ", ");
154 #ifdef HAVE_LIBZ
155         g_string_append(str, "with libz ");
156 #ifdef ZLIB_VERSION
157         g_string_append(str, ZLIB_VERSION);
158 #else /* ZLIB_VERSION */
159         g_string_append(str, "(version unknown)");
160 #endif /* ZLIB_VERSION */
161 #else /* HAVE_LIBZ */
162         g_string_append(str, "without libz");
163 #endif /* HAVE_LIBZ */
164
165         /* LIBCAP */
166         g_string_append(str, ", ");
167 #ifdef HAVE_LIBCAP
168         g_string_append(str, "with POSIX capabilities");
169 #ifdef _LINUX_CAPABILITY_VERSION
170         g_string_append(str, " (Linux)");
171 #endif /* _LINUX_CAPABILITY_VERSION */
172 #else /* HAVE_LIBCAP */
173         g_string_append(str, "without POSIX capabilities");
174 #endif /* HAVE_LIBCAP */
175
176         /* Additional application-dependent information */
177         if (additional_info)
178                 (*additional_info)(str);
179         g_string_append(str, ".");
180
181 #ifndef HAVE_LIBPCRE
182         g_string_append(str,
183         "\nNOTE: this build doesn't support the \"matches\" operator for Wireshark filter syntax");
184         g_string_append(str, ".");
185 #endif  /* HAVE_LIBPCRE */
186
187         end_string(str);
188 }
189
190 /*
191  * Get compile-time information used only by applications that use
192  * libwireshark.
193  */
194 void
195 get_epan_compiled_version_info(GString *str)
196 {
197         /* PCRE */
198         g_string_append(str, ", ");
199 #ifdef HAVE_LIBPCRE
200         g_string_append(str, "with libpcre ");
201 #ifdef PCRE_MAJOR
202 #ifdef PCRE_MINOR
203         g_string_append_printf(str, "%u.%u", PCRE_MAJOR, PCRE_MINOR);
204 #else                   /* PCRE_MINOR */
205         g_string_append_printf(str, "%u", PCRE_MAJOR);
206 #endif                  /* PCRE_MINOR */
207 #else           /* PCRE_MAJOR */
208         g_string_append(str, "(version unknown)");
209 #endif          /* PCRE_MAJOR */
210 #else   /* HAVE_LIBPCRE */
211         g_string_append(str, "without libpcre");
212 #endif  /* HAVE_LIBPCRE */
213
214         /* SNMP */
215         g_string_append(str, ", ");
216 #ifdef HAVE_LIBSMI
217         g_string_append(str, "with SMI ");
218         g_string_append(str, SMI_VERSION_STRING);
219 #else /* no SNMP library */
220         g_string_append(str, "without SMI");
221 #endif /* _SMI_H */
222
223         /* c-ares */
224         g_string_append(str, ", ");
225 #ifdef HAVE_C_ARES
226         g_string_append(str, "with c-ares ");
227         g_string_append(str, ARES_VERSION_STR);
228 #else
229         g_string_append(str, "without c-ares");
230 #endif /* HAVE_C_ARES */
231
232         /* ADNS */
233         g_string_append(str, ", ");
234 #ifdef HAVE_GNU_ADNS
235         g_string_append(str, "with ADNS");
236 #else
237         g_string_append(str, "without ADNS");
238 #endif /* HAVE_GNU_ADNS */
239
240         /* LUA */
241         g_string_append(str, ", ");
242 #ifdef HAVE_LUA_5_1
243         g_string_append(str, "with ");
244         g_string_append(str, LUA_VERSION);
245 #else
246         g_string_append(str, "without Lua");
247 #endif /* HAVE_LUA_5_1 */
248
249         /* GnuTLS */
250         g_string_append(str, ", ");
251 #ifdef HAVE_LIBGNUTLS
252         g_string_append(str, "with GnuTLS " LIBGNUTLS_VERSION);
253 #else
254         g_string_append(str, "without GnuTLS");
255 #endif /* HAVE_LIBGNUTLS */
256
257         /* Gcrypt */
258         g_string_append(str, ", ");
259 #ifdef HAVE_LIBGCRYPT
260         g_string_append(str, "with Gcrypt " GCRYPT_VERSION);
261 #else
262         g_string_append(str, "without Gcrypt");
263 #endif /* HAVE_LIBGCRYPT */
264
265         /* Kerberos */
266         /* XXX - I don't see how to get the version number, at least for KfW */
267         g_string_append(str, ", ");
268 #ifdef HAVE_KERBEROS
269 #ifdef HAVE_MIT_KERBEROS
270         g_string_append(str, "with MIT Kerberos");
271 #else
272         /* HAVE_HEIMDAL_KERBEROS */
273         g_string_append(str, "with Heimdal Kerberos");
274 #endif
275 #else
276         g_string_append(str, "without Kerberos");
277 #endif /* HAVE_KERBEROS */
278 }
279
280 /*
281  * Get various library run-time versions, and the OS version, and append
282  * them to the specified GString.
283  */
284 void
285 get_runtime_version_info(GString *str, void (*additional_info)(GString *))
286 {
287 #if defined(_WIN32)
288         OSVERSIONINFO info;
289 #elif defined(HAVE_SYS_UTSNAME_H)
290         struct utsname name;
291 #endif
292 #if HAVE_OS_X_FRAMEWORKS
293         long macosx_ver, macosx_major_ver, macosx_minor_ver, macosx_bugfix_ver;
294 #endif
295
296         g_string_append(str, "on ");
297
298 #if defined(_WIN32)
299         /*
300          * See
301          *
302          *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getting_the_system_version.asp
303          *
304          * for more than you ever wanted to know about determining the
305          * flavor of Windows on which you're running.  Implementing more
306          * of that is left as an exercise to the reader - who should
307          * check any copyright information about code samples on MSDN
308          * before cutting and pasting into Wireshark.
309          *
310          * They should also note that you need an OSVERSIONINFOEX structure
311          * to get some of that information, and that not only is that
312          * structure not supported on older versions of Windows, you might
313          * not even be able to compile code that *uses* that structure with
314          * older versions of the SDK.
315          */
316         info.dwOSVersionInfoSize = sizeof info;
317         if (!GetVersionEx(&info)) {
318                 /*
319                  * XXX - get the failure reason.
320                  */
321                 g_string_append(str, "unknown Windows version");
322                 return;
323         }
324         switch (info.dwPlatformId) {
325
326         case VER_PLATFORM_WIN32s:
327                 /* Shyeah, right. */
328                 g_string_append_printf(str, "Windows 3.1 with Win32s");
329                 break;
330
331         case VER_PLATFORM_WIN32_WINDOWS:
332                 /* Windows OT */
333                 switch (info.dwMajorVersion) {
334
335                 case 4:
336                         /* 3 cheers for Microsoft marketing! */
337                         switch (info.dwMinorVersion) {
338
339                         case 0:
340                                 g_string_append_printf(str, "Windows 95");
341                                 break;
342
343                         case 10:
344                                 g_string_append_printf(str, "Windows 98");
345                                 break;
346
347                         case 90:
348                                 g_string_append_printf(str, "Windows Me");
349                                 break;
350
351                         default:
352                                 g_string_append_printf(str, "Windows OT, unknown version %lu.%lu",
353                                     info.dwMajorVersion, info.dwMinorVersion);
354                                 break;
355                         }
356                         break;
357
358                 default:
359                         g_string_append_printf(str, "Windows OT, unknown version %lu.%lu",
360                             info.dwMajorVersion, info.dwMinorVersion);
361                         break;
362                 }
363                 break;
364
365         case VER_PLATFORM_WIN32_NT:
366                 /* Windows NT */
367                 switch (info.dwMajorVersion) {
368
369                 case 3:
370                 case 4:
371                         g_string_append_printf(str, "Windows NT %lu.%lu",
372                             info.dwMajorVersion, info.dwMinorVersion);
373                         break;
374
375                 case 5:
376                         /* 3 cheers for Microsoft marketing! */
377                         switch (info.dwMinorVersion) {
378
379                         case 0:
380                                 g_string_append_printf(str, "Windows 2000");
381                                 break;
382
383                         case 1:
384                                 g_string_append_printf(str, "Windows XP");
385                                 break;
386
387                         case 2:
388                                 g_string_append_printf(str, "Windows Server 2003");
389                                 break;
390
391                         default:
392                                 g_string_append_printf(str, "Windows NT, unknown version %lu.%lu",
393                                     info.dwMajorVersion, info.dwMinorVersion);
394                                 break;
395                         }
396                         break;
397
398                 case 6:
399                         g_string_append_printf(str, "Windows Vista");
400                         break;
401
402                 default:
403                         g_string_append_printf(str, "Windows NT, unknown version %lu.%lu",
404                             info.dwMajorVersion, info.dwMinorVersion);
405                         break;
406                 }
407                 break;
408
409         default:
410                 g_string_append_printf(str, "Unknown Windows platform %lu version %lu.%lu",
411                     info.dwPlatformId, info.dwMajorVersion, info.dwMinorVersion);
412                 break;
413         }
414         if (info.szCSDVersion[0] != '\0')
415                 g_string_append_printf(str, " %s", utf_16to8(info.szCSDVersion));
416         g_string_append_printf(str, ", build %lu", info.dwBuildNumber);
417 #elif defined(HAVE_SYS_UTSNAME_H)
418         /*
419          * We have <sys/utsname.h>, so we assume we have "uname()".
420          */
421         if (uname(&name) < 0) {
422                 g_string_append_printf(str, "unknown OS version (uname failed - %s)",
423                     strerror(errno));
424                 return;
425         }
426
427         if (strcmp(name.sysname, "AIX") == 0) {
428                 /*
429                  * Yay, IBM!  Thanks for doing something different
430                  * from most of the other UNIXes out there, and
431                  * making "name.version" apparently be the major
432                  * version number and "name.release" be the minor
433                  * version number.
434                  */
435                 g_string_append_printf(str, "%s %s.%s", name.sysname, name.version,
436                     name.release);
437         } else {
438                 /*
439                  * XXX - get "version" on any other platforms?
440                  *
441                  * On Digital/Tru64 UNIX, it's something unknown.
442                  * On Solaris, it's some kind of build information.
443                  * On HP-UX, it appears to be some sort of subrevision
444                  * thing.
445                  */
446                 g_string_append_printf(str, "%s %s", name.sysname, name.release);
447 #ifdef HAVE_OS_X_FRAMEWORKS
448                 Gestalt(gestaltSystemVersion, &macosx_ver);
449
450                 /* The following functions are only available in MacOS 10.4+ */
451                 if(macosx_ver >= 0x1040) {
452                         Gestalt(gestaltSystemVersionMajor, &macosx_major_ver);
453                         Gestalt(gestaltSystemVersionMinor, &macosx_minor_ver);
454                         Gestalt(gestaltSystemVersionBugFix, &macosx_bugfix_ver);
455
456                         g_string_append_printf(str, " (MacOS %ld.%ld.%ld)",
457                                           macosx_major_ver,
458                                           macosx_minor_ver,
459                                           macosx_bugfix_ver);
460                 } else {
461                         g_string_append_printf(str, " (MacOS X < 10.4 [%lx])",
462                                           macosx_ver);
463                         /* See Apple's Gestalt Manager Reference for meanings
464                          * of the macosx_ver values. */
465                 }
466 #endif /* HAVE_OS_X_FRAMEWORKS */
467         }
468 #else
469         g_string_append(str, "an unknown OS");
470 #endif
471
472         /* Libpcap */
473         g_string_append(str, ", ");
474         get_runtime_pcap_version(str);
475
476         /* Additional application-dependent information */
477         if (additional_info)
478                 (*additional_info)(str);
479
480         g_string_append(str, ".");
481
482         /* Compiler info */
483
484         /*
485          * See http://predef.sourceforge.net/precomp.html for
486          * information on various defined strings.
487          *
488          * GCC's __VERSION__ is a nice text string for humans to
489          * read.  The page at predef.sourceforge.net largely
490          * describes numeric #defines that encode the version;
491          * if the compiler doesn't also offer a nice printable
492          * string, we should probably prettify the number somehow.
493          */
494 #if defined(__GNUC__) && defined(__VERSION__)
495         g_string_append_printf(str, "\n\nBuilt using gcc %s.\n", __VERSION__);
496 #elif defined(__HP_aCC)
497         g_string_append_printf(str, "\n\nBuilt using HP aCC %d.\n", __HP_aCC);
498 #elif defined(__xlC__)
499         g_string_append_printf(str, "\n\nBuilt using IBM XL C %d.%d\n",
500             (__xlC__ >> 8) & 0xFF, __xlC__ & 0xFF);
501 #ifdef __IBMC__
502         if ((__IBMC__ % 10) != 0)
503                 g_string_append_printf(str, " patch %d", __IBMC__ % 10);
504 #endif /* __IBMC__ */
505         g_string_append_printf(str, "\n");
506 #elif defined(__INTEL_COMPILER)
507         g_string_append_printf(str, "\n\nBuilt using Intel C %d.%d",
508             __INTEL_COMPILER / 100, (__INTEL_COMPILER / 10) % 10);
509         if ((__INTEL_COMPILER % 10) != 0)
510                 g_string_append_printf(str, " patch %d", __INTEL_COMPILER % 10);
511 #ifdef __INTEL_COMPILER_BUILD_DATE
512         g_string_sprinta(str, ", compiler built %04d-%02d-%02d",
513             __INTEL_COMPILER_BUILD_DATE / 10000,
514             (__INTEL_COMPILER_BUILD_DATE / 100) % 100,
515             __INTEL_COMPILER_BUILD_DATE % 100);
516 #endif /* __INTEL_COMPILER_BUILD_DATE */
517         g_string_append_printf(str, "\n");
518 #elif defined(_MSC_FULL_VER)
519         if (_MSC_FULL_VER > 99999999) {
520                 g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d",
521                     (_MSC_FULL_VER / 10000000) - 6,
522                     (_MSC_FULL_VER / 100000) % 100);
523                 if ((_MSC_FULL_VER % 100000) != 0)
524                         g_string_append_printf(str, " build %d",
525                             _MSC_FULL_VER % 100000);
526         } else {
527                 g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d",
528                     (_MSC_FULL_VER / 1000000) - 6,
529                     (_MSC_FULL_VER / 10000) % 100);
530                 if ((_MSC_FULL_VER % 10000) != 0)
531                         g_string_append_printf(str, " build %d",
532                             _MSC_FULL_VER % 10000);
533         }
534         g_string_append_printf(str, "\n");
535 #elif defined(_MSC_VER)
536         /* _MSC_FULL_VER not defined, but _MSC_VER defined */
537         g_string_append_printf(str, "\n\nBuilt using Microsoft Visual C++ %d.%d\n",
538             (_MSC_VER / 100) - 6, _MSC_VER % 100);
539 #elif defined(__SUNPRO_C)
540         g_string_append_printf(str, "\n\nBuilt using Sun C %d.%d",
541             (__SUNPRO_C >> 8) & 0xF, (__SUNPRO_C >> 4) & 0xF);
542         if ((__SUNPRO_C & 0xF) != 0)
543                 g_string_append_printf(str, " patch %d", __SUNPRO_C & 0xF);
544         g_string_append_printf(str, "\n");
545 #endif
546
547         end_string(str);
548 }
549
550 /*
551  * Get copyright information.
552  */
553 const char *
554 get_copyright_info(void)
555 {
556         return
557 "Copyright 1998-2008 Gerald Combs <gerald@wireshark.org> and contributors.\n"
558 "This is free software; see the source for copying conditions. There is NO\n"
559 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
560 }
561
562 #if defined(_WIN32)
563 /*
564  * Get the major OS version.
565  */
566 /* XXX - Should this return the minor version as well, e.g. 0x00050002? */
567 guint32
568 get_os_major_version()
569 {
570         OSVERSIONINFO info;
571         info.dwOSVersionInfoSize = sizeof info;
572         if (GetVersionEx(&info)) {
573                 return info.dwMajorVersion;
574         }
575         return 0;
576 }
577 #endif
578
579 /*
580  * Editor modelines
581  *
582  * Local Variables:
583  * c-basic-offset: 8
584  * tab-width: 8
585  * indent-tabs-mode: tabs
586  * End:
587  *
588  * ex: set shiftwidth=8 tabstop=8 noexpandtab
589  * :indentSize=8:tabSize=8:noTabs=false:
590  */