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