NeoMutt  2024-12-12-19-ge4b57e
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 ENABLE_NLS
212 { "nls", 1 },
213#else
214 { "nls", 0 },
215#endif
216#ifdef USE_NOTMUCH
217 { "notmuch", 1 },
218#else
219 { "notmuch", 0 },
220#endif
221#ifdef USE_SSL_OPENSSL
222 { "openssl", 1 },
223#else
224 { "openssl", 0 },
225#endif
226#ifdef HAVE_PCRE2
227 { "pcre2", 1 },
228#endif
229#ifdef CRYPT_BACKEND_CLASSIC_PGP
230 { "pgp", 1 },
231#else
232 { "pgp", 0 },
233#endif
234#ifndef HAVE_PCRE2
235 { "regex", 1 },
236#endif
237#ifdef USE_SASL_CYRUS
238 { "sasl", 1 },
239#else
240 { "sasl", 0 },
241#endif
242#ifdef CRYPT_BACKEND_CLASSIC_SMIME
243 { "smime", 1 },
244#else
245 { "smime", 0 },
246#endif
247#ifdef USE_SQLITE
248 { "sqlite", 1 },
249#else
250 { "sqlite", 0 },
251#endif
252#ifdef NEOMUTT_DIRECT_COLORS
253 { "truecolor", 1 },
254#else
255 { "truecolor", 0 },
256#endif
257 { NULL, 0 },
258};
259
261static const struct CompileOptions DebugOpts[] = {
262#ifdef USE_ASAN
263 { "asan", 2 },
264#endif
265#ifdef USE_DEBUG_BACKTRACE
266 { "backtrace", 2 },
267#endif
268#ifdef USE_DEBUG_COLOR
269 { "color", 2 },
270#endif
271#ifdef USE_DEBUG_EMAIL
272 { "email", 2 },
273#endif
274#ifdef USE_DEBUG_GRAPHVIZ
275 { "graphviz", 2 },
276#endif
277#ifdef USE_DEBUG_KEYMAP
278 { "keymap", 2 },
279#endif
280#ifdef USE_DEBUG_LOGGING
281 { "logging", 2 },
282#endif
283#ifdef USE_DEBUG_NAMES
284 { "names", 2 },
285#endif
286#ifdef USE_DEBUG_NOTIFY
287 { "notify", 2 },
288#endif
289#ifdef QUEUE_MACRO_DEBUG_TRACE
290 { "queue", 2 },
291#endif
292#ifdef USE_UBSAN
293 { "ubsan", 2 },
294#endif
295#ifdef USE_DEBUG_WINDOW
296 { "window", 2 },
297#endif
298 { NULL, 0 },
299};
300
314static void print_compile_options(const struct CompileOptions *co, FILE *fp)
315{
316 if (!co || !fp)
317 return;
318
319 size_t used = 2;
320 bool tty = isatty(fileno(fp));
321
322 fprintf(fp, " ");
323 for (int i = 0; co[i].name; i++)
324 {
325 const size_t len = strlen(co[i].name) + 2; /* +/- and a space */
326 if ((used + len) > SCREEN_WIDTH)
327 {
328 used = 2;
329 fprintf(fp, "\n ");
330 }
331 used += len;
332 const char *fmt = "?%s ";
333 switch (co[i].enabled)
334 {
335 case 0: // Disabled
336 if (tty)
337 fmt = "\033[1;31m-%s\033[0m "; // Escape, red
338 else
339 fmt = "-%s ";
340 break;
341 case 1: // Enabled
342 if (tty)
343 fmt = "\033[1;32m+%s\033[0m "; // Escape, green
344 else
345 fmt = "+%s ";
346 break;
347 case 2: // Devel only
348 if (tty)
349 fmt = "\033[1;36m%s\033[0m "; // Escape, cyan
350 else
351 fmt = "%s ";
352 break;
353 }
354 fprintf(fp, fmt, co[i].name);
355 }
356 fprintf(fp, "\n");
357}
358
366static char *rstrip_in_place(char *s)
367{
368 if (!s)
369 return NULL;
370
371 char *p = &s[strlen(s)];
372 if (p == s)
373 return s;
374 p--;
375 while ((p >= s) && ((*p == '\n') || (*p == '\r')))
376 *p-- = '\0';
377 return s;
378}
379
388bool print_version(FILE *fp)
389{
390 if (!fp)
391 return false;
392
393 struct utsname uts = { 0 };
394 bool tty = isatty(fileno(fp));
395
396 const char *col_cyan = "";
397 const char *col_bold = "";
398 const char *col_end = "";
399
400 if (tty)
401 {
402 col_cyan = "\033[1;36m"; // Escape, cyan
403 col_bold = "\033[1m"; // Escape, bold
404 col_end = "\033[0m"; // Escape, end
405 }
406
407 fprintf(fp, "%s%s%s\n", col_cyan, mutt_make_version(), col_end);
408 fprintf(fp, "%s\n", _(Notice));
409
410 uname(&uts);
411
412 fprintf(fp, "%sSystem:%s ", col_bold, col_end);
413#ifdef SCO
414 fprintf(fp, "SCO %s", uts.release);
415#else
416 fprintf(fp, "%s %s", uts.sysname, uts.release);
417#endif
418
419 fprintf(fp, " (%s)", uts.machine);
420
421 fprintf(fp, "\n%sncurses:%s %s", col_bold, col_end, curses_version());
422#ifdef NCURSES_VERSION
423 fprintf(fp, " (compiled with %s.%d)", NCURSES_VERSION, NCURSES_VERSION_PATCH);
424#endif
425
426#ifdef _LIBICONV_VERSION
427 fprintf(fp, "\n%slibiconv:%s %d.%d", col_bold, col_end,
428 _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 0xff);
429#endif
430
431#ifdef HAVE_LIBIDN
432 fprintf(fp, "\n%slibidn2:%s %s", col_bold, col_end, mutt_idna_print_version());
433#endif
434
435#ifdef CRYPT_BACKEND_GPGME
436 fprintf(fp, "\n%sGPGME:%s %s", col_bold, col_end, mutt_gpgme_print_version());
437#endif
438
439#ifdef USE_SSL_OPENSSL
440#ifdef LIBRESSL_VERSION_TEXT
441 fprintf(fp, "\n%sLibreSSL:%s %s", col_bold, col_end, LIBRESSL_VERSION_TEXT);
442#endif
443#ifdef OPENSSL_VERSION_TEXT
444 fprintf(fp, "\n%sOpenSSL:%s %s", col_bold, col_end, OPENSSL_VERSION_TEXT);
445#endif
446#endif
447
448#ifdef USE_SSL_GNUTLS
449 fprintf(fp, "\n%sGnuTLS:%s %s", col_bold, col_end, GNUTLS_VERSION);
450#endif
451
452#ifdef HAVE_NOTMUCH
453 fprintf(fp, "\n%slibnotmuch:%s %d.%d.%d", col_bold, col_end, LIBNOTMUCH_MAJOR_VERSION,
454 LIBNOTMUCH_MINOR_VERSION, LIBNOTMUCH_MICRO_VERSION);
455#endif
456
457#ifdef HAVE_PCRE2
458 {
459 char version[24] = { 0 };
460 pcre2_config(PCRE2_CONFIG_VERSION, version);
461 fprintf(fp, "\n%sPCRE2:%s %s", col_bold, col_end, version);
462 }
463#endif
464
465#ifdef USE_HCACHE
466 const char *backends = store_backend_list();
467 fprintf(fp, "\n%sstorage:%s %s", col_bold, col_end, backends);
468 FREE(&backends);
469#ifdef USE_HCACHE_COMPRESSION
470 backends = compress_list();
471 fprintf(fp, "\n%scompression:%s %s", col_bold, col_end, backends);
472 FREE(&backends);
473#endif
474#endif
475
477 fprintf(fp, "\n\n%sConfigure options:%s %s\n", col_bold, col_end, (char *) configure_options);
478
479 rstrip_in_place((char *) cc_cflags);
480 fprintf(fp, "\n%sCompilation CFLAGS:%s %s\n", col_bold, col_end, (char *) cc_cflags);
481
482 fprintf(fp, "\n%s%s%s\n", col_bold, _("Compile options:"), col_end);
484
485 if (DebugOpts[0].name)
486 {
487 fprintf(fp, "\n%s%s%s\n", col_bold, _("Devel options:"), col_end);
489 }
490
491 fprintf(fp, "\n");
492#ifdef DOMAIN
493 fprintf(fp, "DOMAIN=\"%s\"\n", DOMAIN);
494#endif
495#ifdef ISPELL
496 fprintf(fp, "ISPELL=\"%s\"\n", ISPELL);
497#endif
498 fprintf(fp, "MAILPATH=\"%s\"\n", MAILPATH);
499 fprintf(fp, "PKGDATADIR=\"%s\"\n", PKGDATADIR);
500 fprintf(fp, "SENDMAIL=\"%s\"\n", SENDMAIL);
501 fprintf(fp, "SYSCONFDIR=\"%s\"\n", SYSCONFDIR);
502
503 fprintf(fp, "\n");
504 fputs(_(ReachingUs), fp);
505
506 fflush(fp);
507 return !ferror(fp);
508}
509
518{
519 puts(mutt_make_version());
520 puts(Copyright);
521 puts(_(Thanks));
522 puts(_(License));
523 puts(_(ReachingUs));
524
525 fflush(stdout);
526 return !ferror(stdout);
527}
528
544bool feature_enabled(const char *name)
545{
546 if (!name)
547 return false;
548 for (int i = 0; CompOpts[i].name; i++)
549 {
550 if (mutt_str_equal(name, CompOpts[i].name))
551 {
552 return CompOpts[i].enabled;
553 }
554 }
555 return false;
556}
Email Address Handling.
#define ISPELL
Definition: config.c:40
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:4163
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:55
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:660
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:314
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:858
bool print_copyright(void)
Print copyright message.
Definition: version.c:517
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:261
bool print_version(FILE *fp)
Print system and compile info to a file.
Definition: version.c:388
unsigned char cc_cflags[]
static char * rstrip_in_place(char *s)
Strip a trailing carriage return.
Definition: version.c:366
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:544
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.