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