NeoMutt  2024-03-23-147-g885fbc
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
version.c
Go to the documentation of this file.
1
30#include "config.h"
31#include <stdbool.h>
32#include <stdio.h>
33#include <string.h>
34#include <sys/utsname.h>
35#include <unistd.h>
36#include "mutt/lib.h"
37#include "gui/lib.h"
38#include "version.h"
39#include "compress/lib.h"
40#ifdef HAVE_LIBIDN
41#include "address/lib.h"
42#endif
43#ifdef CRYPT_BACKEND_GPGME
44#include "ncrypt/lib.h"
45#endif
46#ifdef HAVE_NOTMUCH
47#include <notmuch.h>
48#endif
49#ifdef USE_SSL_OPENSSL
50#include <openssl/opensslv.h>
51#endif
52#ifdef USE_SSL_GNUTLS
53#include <gnutls/gnutls.h>
54#endif
55#ifdef HAVE_PCRE2
56#define PCRE2_CODE_UNIT_WIDTH 8
57#include <pcre2.h>
58#endif
59
60const char *mutt_make_version(void);
61const char *store_backend_list(void);
62const char *store_compress_list(void);
63
65static const int SCREEN_WIDTH = 80;
66
67extern unsigned char cc_cflags[];
68extern unsigned char configure_options[];
69
71static const char *Copyright =
72 "Copyright (C) 2015-2024 Richard Russon <rich@flatcap.org>\n"
73 "Copyright (C) 2016-2023 Pietro Cerutti <gahr@gahr.ch>\n"
74 "Copyright (C) 2017-2019 Mehdi Abaakouk <sileht@sileht.net>\n"
75 "Copyright (C) 2018-2020 Federico Kircheis <federico.kircheis@gmail.com>\n"
76 "Copyright (C) 2017-2022 Austin Ray <austin@austinray.io>\n"
77 "Copyright (C) 2023-2024 Dennis Schön <mail@dennis-schoen.de>\n"
78 "Copyright (C) 2016-2017 Damien Riegel <damien.riegel@gmail.com>\n"
79 "Copyright (C) 2023 Rayford Shireman\n"
80 "Copyright (C) 2021-2023 David Purton <dcpurton@marshwiggle.net>\n"
81 "Copyright (C) 2020-2023 наб <nabijaczleweli@nabijaczleweli.xyz>\n";
82
84static const char *Thanks = N_(
85 "Many others not mentioned here contributed code, fixes and suggestions.\n");
86
88static const char *License = N_(
89 "This program is free software; you can redistribute it and/or modify\n"
90 "it under the terms of the GNU General Public License as published by\n"
91 "the Free Software Foundation; either version 2 of the License, or\n"
92 "(at your option) any later version.\n"
93 "\n"
94 "This program is distributed in the hope that it will be useful,\n"
95 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
96 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
97 "GNU General Public License for more details.\n"
98 "\n"
99 "You should have received a copy of the GNU General Public License\n"
100 "along with this program; if not, write to the Free Software\n"
101 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n");
102
104static const char *ReachingUs = N_("To learn more about NeoMutt, visit: https://neomutt.org\n"
105 "If you find a bug in NeoMutt, please raise an issue at:\n"
106 " https://github.com/neomutt/neomutt/issues\n"
107 "or send an email to: <neomutt-devel@neomutt.org>\n");
108
109// clang-format off
111static const char *Notice =
112 N_("Copyright (C) 2015-2024 Richard Russon and friends\n"
113 "NeoMutt comes with ABSOLUTELY NO WARRANTY; for details type 'neomutt -vv'.\n"
114 "NeoMutt is free software, and you are welcome to redistribute it\n"
115 "under certain conditions; type 'neomutt -vv' for details.\n");
116// clang-format on
117
122{
123 const char *name;
125};
126
127/* These are sorted by the display string */
128
130static const struct CompileOptions CompOpts[] = {
131#ifdef USE_AUTOCRYPT
132 { "autocrypt", 1 },
133#else
134 { "autocrypt", 0 },
135#endif
136#ifdef USE_FCNTL
137 { "fcntl", 1 },
138#else
139 { "fcntl", 0 },
140#endif
141#ifdef USE_FLOCK
142 { "flock", 1 },
143#else
144 { "flock", 0 },
145#endif
146#ifdef USE_FMEMOPEN
147 { "fmemopen", 1 },
148#else
149 { "fmemopen", 0 },
150#endif
151#ifdef HAVE_FUTIMENS
152 { "futimens", 1 },
153#else
154 { "futimens", 0 },
155#endif
156#ifdef HAVE_GETADDRINFO
157 { "getaddrinfo", 1 },
158#else
159 { "getaddrinfo", 0 },
160#endif
161#ifdef USE_SSL_GNUTLS
162 { "gnutls", 1 },
163#else
164 { "gnutls", 0 },
165#endif
166#ifdef CRYPT_BACKEND_GPGME
167 { "gpgme", 1 },
168#else
169 { "gpgme", 0 },
170#endif
171#ifdef USE_SASL_GNU
172 { "gsasl", 1 },
173#else
174 { "gsasl", 0 },
175#endif
176#ifdef USE_GSS
177 { "gss", 1 },
178#else
179 { "gss", 0 },
180#endif
181#ifdef USE_HCACHE
182 { "hcache", 1 },
183#else
184 { "hcache", 0 },
185#endif
186#ifdef HOMESPOOL
187 { "homespool", 1 },
188#else
189 { "homespool", 0 },
190#endif
191#ifdef HAVE_LIBIDN
192 { "idn", 1 },
193#else
194 { "idn", 0 },
195#endif
196#ifdef USE_INOTIFY
197 { "inotify", 1 },
198#else
199 { "inotify", 0 },
200#endif
201#ifdef LOCALES_HACK
202 { "locales_hack", 1 },
203#else
204 { "locales_hack", 0 },
205#endif
206#ifdef USE_LUA
207 { "lua", 1 },
208#else
209 { "lua", 0 },
210#endif
211#ifdef MIXMASTER
212 { "mixmaster", 1 },
213#else
214 { "mixmaster", 0 },
215#endif
216#ifdef ENABLE_NLS
217 { "nls", 1 },
218#else
219 { "nls", 0 },
220#endif
221#ifdef USE_NOTMUCH
222 { "notmuch", 1 },
223#else
224 { "notmuch", 0 },
225#endif
226#ifdef USE_SSL_OPENSSL
227 { "openssl", 1 },
228#else
229 { "openssl", 0 },
230#endif
231#ifdef HAVE_PCRE2
232 { "pcre2", 1 },
233#endif
234#ifdef CRYPT_BACKEND_CLASSIC_PGP
235 { "pgp", 1 },
236#else
237 { "pgp", 0 },
238#endif
239#ifndef HAVE_PCRE2
240 { "regex", 1 },
241#endif
242#ifdef USE_SASL_CYRUS
243 { "sasl", 1 },
244#else
245 { "sasl", 0 },
246#endif
247#ifdef CRYPT_BACKEND_CLASSIC_SMIME
248 { "smime", 1 },
249#else
250 { "smime", 0 },
251#endif
252#ifdef USE_SQLITE
253 { "sqlite", 1 },
254#else
255 { "sqlite", 0 },
256#endif
257#ifdef NEOMUTT_DIRECT_COLORS
258 { "truecolor", 1 },
259#else
260 { "truecolor", 0 },
261#endif
262 { NULL, 0 },
263};
264
266static const struct CompileOptions DebugOpts[] = {
267#ifdef USE_ASAN
268 { "asan", 2 },
269#endif
270#ifdef USE_DEBUG_BACKTRACE
271 { "backtrace", 2 },
272#endif
273#ifdef USE_DEBUG_COLOR
274 { "color", 2 },
275#endif
276#ifdef USE_DEBUG_EMAIL
277 { "email", 2 },
278#endif
279#ifdef USE_DEBUG_GRAPHVIZ
280 { "graphviz", 2 },
281#endif
282#ifdef USE_DEBUG_KEYMAP
283 { "keymap", 2 },
284#endif
285#ifdef USE_DEBUG_LOGGING
286 { "logging", 2 },
287#endif
288#ifdef USE_DEBUG_NAMES
289 { "names", 2 },
290#endif
291#ifdef USE_DEBUG_NOTIFY
292 { "notify", 2 },
293#endif
294#ifdef QUEUE_MACRO_DEBUG_TRACE
295 { "queue", 2 },
296#endif
297#ifdef USE_UBSAN
298 { "ubsan", 2 },
299#endif
300#ifdef USE_DEBUG_WINDOW
301 { "window", 2 },
302#endif
303 { NULL, 0 },
304};
305
319static void print_compile_options(const struct CompileOptions *co, FILE *fp)
320{
321 if (!co || !fp)
322 return;
323
324 size_t used = 2;
325 bool tty = isatty(fileno(fp));
326
327 fprintf(fp, " ");
328 for (int i = 0; co[i].name; i++)
329 {
330 const size_t len = strlen(co[i].name) + 2; /* +/- and a space */
331 if ((used + len) > SCREEN_WIDTH)
332 {
333 used = 2;
334 fprintf(fp, "\n ");
335 }
336 used += len;
337 const char *fmt = "?%s ";
338 switch (co[i].enabled)
339 {
340 case 0: // Disabled
341 if (tty)
342 fmt = "\033[1;31m-%s\033[0m "; // Escape, red
343 else
344 fmt = "-%s ";
345 break;
346 case 1: // Enabled
347 if (tty)
348 fmt = "\033[1;32m+%s\033[0m "; // Escape, green
349 else
350 fmt = "+%s ";
351 break;
352 case 2: // Devel only
353 if (tty)
354 fmt = "\033[1;36m%s\033[0m "; // Escape, cyan
355 else
356 fmt = "%s ";
357 break;
358 }
359 fprintf(fp, fmt, co[i].name);
360 }
361 fprintf(fp, "\n");
362}
363
371static char *rstrip_in_place(char *s)
372{
373 if (!s)
374 return NULL;
375
376 char *p = &s[strlen(s)];
377 if (p == s)
378 return s;
379 p--;
380 while ((p >= s) && ((*p == '\n') || (*p == '\r')))
381 *p-- = '\0';
382 return s;
383}
384
393bool print_version(FILE *fp)
394{
395 if (!fp)
396 return false;
397
398 struct utsname uts = { 0 };
399 bool tty = isatty(fileno(fp));
400
401 const char *col_cyan = "";
402 const char *col_bold = "";
403 const char *col_end = "";
404
405 if (tty)
406 {
407 col_cyan = "\033[1;36m"; // Escape, cyan
408 col_bold = "\033[1m"; // Escape, bold
409 col_end = "\033[0m"; // Escape, end
410 }
411
412 fprintf(fp, "%s%s%s\n", col_cyan, mutt_make_version(), col_end);
413 fprintf(fp, "%s\n", _(Notice));
414
415 uname(&uts);
416
417 fprintf(fp, "%sSystem:%s ", col_bold, col_end);
418#ifdef SCO
419 fprintf(fp, "SCO %s", uts.release);
420#else
421 fprintf(fp, "%s %s", uts.sysname, uts.release);
422#endif
423
424 fprintf(fp, " (%s)", uts.machine);
425
426 fprintf(fp, "\n%sncurses:%s %s", col_bold, col_end, curses_version());
427#ifdef NCURSES_VERSION
428 fprintf(fp, " (compiled with %s.%d)", NCURSES_VERSION, NCURSES_VERSION_PATCH);
429#endif
430
431#ifdef _LIBICONV_VERSION
432 fprintf(fp, "\n%slibiconv:%s %d.%d", col_bold, col_end,
433 _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 0xff);
434#endif
435
436#ifdef HAVE_LIBIDN
437 fprintf(fp, "\n%slibidn2:%s %s", col_bold, col_end, mutt_idna_print_version());
438#endif
439
440#ifdef CRYPT_BACKEND_GPGME
441 fprintf(fp, "\n%sGPGME:%s %s", col_bold, col_end, mutt_gpgme_print_version());
442#endif
443
444#ifdef USE_SSL_OPENSSL
445#ifdef LIBRESSL_VERSION_TEXT
446 fprintf(fp, "\n%sLibreSSL:%s %s", col_bold, col_end, LIBRESSL_VERSION_TEXT);
447#endif
448#ifdef OPENSSL_VERSION_TEXT
449 fprintf(fp, "\n%sOpenSSL:%s %s", col_bold, col_end, OPENSSL_VERSION_TEXT);
450#endif
451#endif
452
453#ifdef USE_SSL_GNUTLS
454 fprintf(fp, "\n%sGnuTLS:%s %s", col_bold, col_end, GNUTLS_VERSION);
455#endif
456
457#ifdef HAVE_NOTMUCH
458 fprintf(fp, "\n%slibnotmuch:%s %d.%d.%d", col_bold, col_end, LIBNOTMUCH_MAJOR_VERSION,
459 LIBNOTMUCH_MINOR_VERSION, LIBNOTMUCH_MICRO_VERSION);
460#endif
461
462#ifdef HAVE_PCRE2
463 {
464 char version[24] = { 0 };
465 pcre2_config(PCRE2_CONFIG_VERSION, version);
466 fprintf(fp, "\n%sPCRE2:%s %s", col_bold, col_end, version);
467 }
468#endif
469
470#ifdef USE_HCACHE
471 const char *backends = store_backend_list();
472 fprintf(fp, "\n%sstorage:%s %s", col_bold, col_end, backends);
473 FREE(&backends);
474#ifdef USE_HCACHE_COMPRESSION
475 backends = compress_list();
476 fprintf(fp, "\n%scompression:%s %s", col_bold, col_end, backends);
477 FREE(&backends);
478#endif
479#endif
480
482 fprintf(fp, "\n\n%sConfigure options:%s %s\n", col_bold, col_end, (char *) configure_options);
483
484 rstrip_in_place((char *) cc_cflags);
485 fprintf(fp, "\n%sCompilation CFLAGS:%s %s\n", col_bold, col_end, (char *) cc_cflags);
486
487 fprintf(fp, "\n%s%s%s\n", col_bold, _("Compile options:"), col_end);
489
490 if (DebugOpts[0].name)
491 {
492 fprintf(fp, "\n%s%s%s\n", col_bold, _("Devel options:"), col_end);
494 }
495
496 fprintf(fp, "\n");
497#ifdef DOMAIN
498 fprintf(fp, "DOMAIN=\"%s\"\n", DOMAIN);
499#endif
500#ifdef ISPELL
501 fprintf(fp, "ISPELL=\"%s\"\n", ISPELL);
502#endif
503 fprintf(fp, "MAILPATH=\"%s\"\n", MAILPATH);
504#ifdef MIXMASTER
505 fprintf(fp, "MIXMASTER=\"%s\"\n", MIXMASTER);
506#endif
507 fprintf(fp, "PKGDATADIR=\"%s\"\n", PKGDATADIR);
508 fprintf(fp, "SENDMAIL=\"%s\"\n", SENDMAIL);
509 fprintf(fp, "SYSCONFDIR=\"%s\"\n", SYSCONFDIR);
510
511 fprintf(fp, "\n");
512 fputs(_(ReachingUs), fp);
513
514 fflush(fp);
515 return !ferror(fp);
516}
517
526{
527 puts(mutt_make_version());
528 puts(Copyright);
529 puts(_(Thanks));
530 puts(_(License));
531 puts(_(ReachingUs));
532
533 fflush(stdout);
534 return !ferror(stdout);
535}
536
552bool feature_enabled(const char *name)
553{
554 if (!name)
555 return false;
556 for (int i = 0; CompOpts[i].name; i++)
557 {
558 if (mutt_str_equal(name, CompOpts[i].name))
559 {
560 return CompOpts[i].enabled;
561 }
562 }
563 return false;
564}
Email Address Handling.
#define ISPELL
Definition: config.c:39
const char * compress_list(void)
Get a list of compression backend names.
Definition: compress.c:58
API for the header cache compression.
const char * mutt_gpgme_print_version(void)
Get version of GPGME.
Definition: crypt_gpgme.c:4118
Convenience wrapper for the gui headers.
const char * mutt_idna_print_version(void)
Create an IDN version string.
Definition: idna.c:272
#define FREE(x)
Definition: memory.h:45
Convenience wrapper for the library headers.
#define N_(a)
Definition: message.h:32
#define _(a)
Definition: message.h:28
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:709
API for encryption/signing of emails.
List of built-in capabilities.
Definition: version.c:122
const char * name
Option name.
Definition: version.c:123
int enabled
0 Disabled, 1 Enabled, 2 Devel only
Definition: version.c:124
static void print_compile_options(const struct CompileOptions *co, FILE *fp)
Print a list of enabled/disabled features.
Definition: version.c:319
static const char * Thanks
CLI Version: Thanks.
Definition: version.c:84
static const char * License
CLI Version: License.
Definition: version.c:88
static const char * Copyright
CLI Version: Authors' copyrights.
Definition: version.c:71
static const int SCREEN_WIDTH
CLI: Width to wrap version info.
Definition: version.c:65
static const char * ReachingUs
CLI Version: How to reach the NeoMutt Team.
Definition: version.c:104
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:893
bool print_copyright(void)
Print copyright message.
Definition: version.c:525
static const struct CompileOptions CompOpts[]
Compile options strings for neomutt -v output.
Definition: version.c:130
unsigned char configure_options[]
static const struct CompileOptions DebugOpts[]
Debug options strings for neomutt -v output.
Definition: version.c:266
bool print_version(FILE *fp)
Print system and compile info to a file.
Definition: version.c:393
unsigned char cc_cflags[]
static char * rstrip_in_place(char *s)
Strip a trailing carriage return.
Definition: version.c:371
static const char * Notice
CLI Version: Warranty notice.
Definition: version.c:111
bool feature_enabled(const char *name)
Test if a compile-time feature is enabled.
Definition: version.c:552
const char * store_compress_list(void)
const char * store_backend_list(void)
Get a list of backend names.
Definition: store.c:84
Display version and copyright about NeoMutt.