NeoMutt  2020-08-07-1-gab41a1
Teaching an old dog new tricks
DOXYGEN
version.c
Go to the documentation of this file.
1 
31 #include "config.h"
32 #include <stdbool.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <sys/utsname.h>
36 #include <unistd.h>
37 #include "mutt/lib.h"
38 #include "gui/lib.h"
39 #include "version.h"
40 #include "compress/lib.h"
41 #ifdef HAVE_LIBIDN
42 #include "address/lib.h"
43 #endif
44 #ifdef CRYPT_BACKEND_GPGME
45 #include "ncrypt/lib.h"
46 #endif
47 #ifdef HAVE_NOTMUCH
48 #include <notmuch.h>
49 #endif
50 #ifdef USE_SSL_OPENSSL
51 #include <openssl/opensslv.h>
52 #endif
53 #ifdef USE_SSL_GNUTLS
54 #include <gnutls/gnutls.h>
55 #endif
56 #ifdef HAVE_PCRE2
57 #define PCRE2_CODE_UNIT_WIDTH 8
58 #include <pcre2.h>
59 #endif
60 
61 /* #include "muttlib.h" */
62 const char *mutt_make_version(void);
63 /* #include "store/lib.h" */
64 const char *store_backend_list(void);
65 const char *store_compress_list(void);
66 
67 const int SCREEN_WIDTH = 80;
68 
69 extern unsigned char cc_cflags[];
70 extern unsigned char configure_options[];
71 
72 static const char *Copyright =
73  "Copyright (C) 1996-2020 Michael R. Elkins <me@mutt.org>\n"
74  "Copyright (C) 1996-2002 Brandon Long <blong@fiction.net>\n"
75  "Copyright (C) 1997-2009 Thomas Roessler <roessler@does-not-exist.org>\n"
76  "Copyright (C) 1998-2005 Werner Koch <wk@isil.d.shuttle.de>\n"
77  "Copyright (C) 1999-2017 Brendan Cully <brendan@kublai.com>\n"
78  "Copyright (C) 1999-2002 Tommi Komulainen <Tommi.Komulainen@iki.fi>\n"
79  "Copyright (C) 2000-2004 Edmund Grimley Evans <edmundo@rano.org>\n"
80  "Copyright (C) 2006-2009 Rocco Rutte <pdmef@gmx.net>\n"
81  "Copyright (C) 2014-2020 Kevin J. McCarthy <kevin@8t8.us>\n"
82  "Copyright (C) 2015-2020 Richard Russon <rich@flatcap.org>\n";
83 
84 static const char *Thanks =
85  N_("Many others not mentioned here contributed code, fixes,\n"
86  "and suggestions.\n");
87 
88 static 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 "
102  "02110-1301, USA.\n");
103 
104 static const char *ReachingUs =
105  N_("To learn more about NeoMutt, visit: https://neomutt.org\n"
106  "If you find a bug in NeoMutt, please raise an issue at:\n"
107  " https://github.com/neomutt/neomutt/issues\n"
108  "or send an email to: <neomutt-devel@neomutt.org>\n");
109 
110 // clang-format off
111 static const char *Notice =
112  N_("Copyright (C) 1996-2020 Michael R. Elkins and others.\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;
124  int enabled;
125 };
126 
127 /* These are sorted by the display string */
128 
129 static struct CompileOptions comp_opts_default[] = {
130  { "attach_headers_color", 1 },
131  { "compose_to_sender", 1 },
132  { "compress", 1 },
133  { "cond_date", 1 },
134  { "debug", 1 },
135  { "encrypt_to_self", 1 },
136  { "forgotten_attachments", 1 },
137  { "forwref", 1 },
138  { "ifdef", 1 },
139  { "imap", 1 },
140  { "index_color", 1 },
141  { "initials", 1 },
142  { "limit_current_thread", 1 },
143  { "multiple_fcc", 1 },
144  { "nested_if", 1 },
145  { "new_mail", 1 },
146  { "nntp", 1 },
147  { "pop", 1 },
148  { "progress", 1 },
149  { "quasi_delete", 1 },
150  { "regcomp", 1 },
151  { "reply_with_xorig", 1 },
152  { "sensible_browser", 1 },
153  { "sidebar", 1 },
154  { "skip_quoted", 1 },
155  { "smtp", 1 },
156  { "status_color", 1 },
157  { "timeout", 1 },
158  { "tls_sni", 1 },
159  { "trash", 1 },
160  { NULL, 0 },
161 };
162 
163 static struct CompileOptions comp_opts[] = {
164 #ifdef USE_AUTOCRYPT
165  { "autocrypt", 1 },
166 #else
167  { "autocrypt", 0 },
168 #endif
169 #ifdef HAVE_LIBUNWIND
170  { "backtrace", 2 },
171 #endif
172 #ifdef HAVE_BKGDSET
173  { "bkgdset", 1 },
174 #else
175  { "bkgdset", 0 },
176 #endif
177 #ifdef HAVE_COLOR
178  { "color", 1 },
179 #else
180  { "color", 0 },
181 #endif
182 #ifdef HAVE_CURS_SET
183  { "curs_set", 1 },
184 #else
185  { "curs_set", 0 },
186 #endif
187 #ifdef USE_FCNTL
188  { "fcntl", 1 },
189 #else
190  { "fcntl", 0 },
191 #endif
192 #ifdef USE_FLOCK
193  { "flock", 1 },
194 #else
195  { "flock", 0 },
196 #endif
197 #ifdef USE_FMEMOPEN
198  { "fmemopen", 1 },
199 #else
200  { "fmemopen", 0 },
201 #endif
202 #ifdef HAVE_FUTIMENS
203  { "futimens", 1 },
204 #else
205  { "futimens", 0 },
206 #endif
207 #ifdef HAVE_GETADDRINFO
208  { "getaddrinfo", 1 },
209 #else
210  { "getaddrinfo", 0 },
211 #endif
212 #ifdef USE_SSL_GNUTLS
213  { "gnutls", 1 },
214 #else
215  { "gnutls", 0 },
216 #endif
217 #ifdef CRYPT_BACKEND_GPGME
218  { "gpgme", 1 },
219 #else
220  { "gpgme", 0 },
221 #endif
222 #ifdef USE_DEBUG_GRAPHVIZ
223  { "graphviz", 2 },
224 #endif
225 #ifdef USE_GSS
226  { "gss", 1 },
227 #else
228  { "gss", 0 },
229 #endif
230 #ifdef USE_HCACHE
231  { "hcache", 1 },
232 #else
233  { "hcache", 0 },
234 #endif
235 #ifdef HOMESPOOL
236  { "homespool", 1 },
237 #else
238  { "homespool", 0 },
239 #endif
240 #ifdef HAVE_LIBIDN
241  { "idn", 1 },
242 #else
243  { "idn", 0 },
244 #endif
245 #ifdef USE_INOTIFY
246  { "inotify", 1 },
247 #else
248  { "inotify", 0 },
249 #endif
250 #ifdef LOCALES_HACK
251  { "locales_hack", 1 },
252 #else
253  { "locales_hack", 0 },
254 #endif
255 #ifdef USE_LUA
256  { "lua", 1 },
257 #else
258  { "lua", 0 },
259 #endif
260 #ifdef HAVE_META
261  { "meta", 1 },
262 #else
263  { "meta", 0 },
264 #endif
265 #ifdef MIXMASTER
266  { "mixmaster", 1 },
267 #else
268  { "mixmaster", 0 },
269 #endif
270 #ifdef ENABLE_NLS
271  { "nls", 1 },
272 #else
273  { "nls", 0 },
274 #endif
275 #ifdef USE_DEBUG_NOTIFY
276  { "notify", 2 },
277 #endif
278 #ifdef USE_NOTMUCH
279  { "notmuch", 1 },
280 #else
281  { "notmuch", 0 },
282 #endif
283 #ifdef USE_SSL_OPENSSL
284  { "openssl", 1 },
285 #else
286  { "openssl", 0 },
287 #endif
288 #ifdef USE_DEBUG_PARSE_TEST
289  { "parse-test", 2 },
290 #endif
291 #ifdef HAVE_PCRE2
292  { "pcre2", 1 },
293 #endif
294 #ifdef CRYPT_BACKEND_CLASSIC_PGP
295  { "pgp", 1 },
296 #else
297  { "pgp", 0 },
298 #endif
299 #ifndef HAVE_PCRE2
300  { "regex", 1 },
301 #endif
302 #ifdef USE_SASL
303  { "sasl", 1 },
304 #else
305  { "sasl", 0 },
306 #endif
307 #ifdef CRYPT_BACKEND_CLASSIC_SMIME
308  { "smime", 1 },
309 #else
310  { "smime", 0 },
311 #endif
312 #ifdef USE_SQLITE
313  { "sqlite", 1 },
314 #else
315  { "sqlite", 0 },
316 #endif
317 #ifdef HAVE_START_COLOR
318  { "start_color", 1 },
319 #else
320  { "start_color", 0 },
321 #endif
322 #ifdef SUN_ATTACHMENT
323  { "sun_attachment", 1 },
324 #else
325  { "sun_attachment", 0 },
326 #endif
327 #ifdef HAVE_TYPEAHEAD
328  { "typeahead", 1 },
329 #else
330  { "typeahead", 0 },
331 #endif
332 #ifdef USE_DEBUG_WINDOW
333  { "window", 2 },
334 #endif
335  { NULL, 0 },
336 };
337 
351 static void print_compile_options(struct CompileOptions *co, FILE *fp)
352 {
353  if (!co || !fp)
354  return;
355 
356  size_t used = 2;
357  bool tty = isatty(fileno(fp));
358 
359  fprintf(fp, " ");
360  for (int i = 0; co[i].name; i++)
361  {
362  const size_t len = strlen(co[i].name) + 2; /* +/- and a space */
363  if ((used + len) > SCREEN_WIDTH)
364  {
365  used = 2;
366  fprintf(fp, "\n ");
367  }
368  used += len;
369  const char *fmt = "?%s ";
370  switch (co[i].enabled)
371  {
372  case 0: // Disabled
373  if (tty)
374  fmt = "\033[1;31m-%s\033[0m "; // Escape, red
375  else
376  fmt = "-%s ";
377  break;
378  case 1: // Enabled
379  if (tty)
380  fmt = "\033[1;32m+%s\033[0m "; // Escape, green
381  else
382  fmt = "+%s ";
383  break;
384  case 2: // Devel only
385  if (tty)
386  fmt = "\033[1;36m!%s\033[0m "; // Escape, cyan
387  else
388  fmt = "!%s ";
389  break;
390  }
391  fprintf(fp, fmt, co[i].name);
392  }
393  fprintf(fp, "\n");
394 }
395 
403 static char *rstrip_in_place(char *s)
404 {
405  if (!s)
406  return NULL;
407 
408  char *p = &s[strlen(s)];
409  if (p == s)
410  return s;
411  p--;
412  while ((p >= s) && ((*p == '\n') || (*p == '\r')))
413  *p-- = '\0';
414  return s;
415 }
416 
424 void print_version(FILE *fp)
425 {
426  if (!fp)
427  return;
428 
429  struct utsname uts;
430  bool tty = isatty(fileno(fp));
431  const char *fmt = "%s\n";
432 
433  if (tty)
434  fmt = "\033[1;36m%s\033[0m\n"; // Escape, cyan
435 
436  fprintf(fp, fmt, mutt_make_version());
437  fprintf(fp, "%s\n", _(Notice));
438 
439  uname(&uts);
440 
441 #ifdef SCO
442  fprintf(fp, "System: SCO %s", uts.release);
443 #else
444  fprintf(fp, "System: %s %s", uts.sysname, uts.release);
445 #endif
446 
447  fprintf(fp, " (%s)", uts.machine);
448 
449 #ifdef NCURSES_VERSION
450  fprintf(fp, "\nncurses: %s (compiled with %s.%d)", curses_version(),
451  NCURSES_VERSION, NCURSES_VERSION_PATCH);
452 #elif defined(USE_SLANG_CURSES)
453  fprintf(fp, "\nslang: %s", SLANG_VERSION_STRING);
454 #endif
455 
456 #ifdef _LIBICONV_VERSION
457  fprintf(fp, "\nlibiconv: %d.%d", _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 0xff);
458 #endif
459 
460 #ifdef HAVE_LIBIDN
461  fprintf(fp, "\n%s", mutt_idna_print_version());
462 #endif
463 
464 #ifdef CRYPT_BACKEND_GPGME
465  fprintf(fp, "\nGPGME: %s", mutt_gpgme_print_version());
466 #endif
467 
468 #ifdef USE_SSL_OPENSSL
469 #ifdef LIBRESSL_VERSION_TEXT
470  fprintf(fp, "\nLibreSSL: %s", LIBRESSL_VERSION_TEXT);
471 #endif
472 #ifdef OPENSSL_VERSION_TEXT
473  fprintf(fp, "\nOpenSSL: %s", OPENSSL_VERSION_TEXT);
474 #endif
475 #endif
476 
477 #ifdef USE_SSL_GNUTLS
478  fprintf(fp, "\nGnuTLS: %s", GNUTLS_VERSION);
479 #endif
480 
481 #ifdef HAVE_NOTMUCH
482  fprintf(fp, "\nlibnotmuch: %d.%d.%d", LIBNOTMUCH_MAJOR_VERSION,
483  LIBNOTMUCH_MINOR_VERSION, LIBNOTMUCH_MICRO_VERSION);
484 #endif
485 
486 #ifdef HAVE_PCRE2
487  {
488  char version[24];
489  pcre2_config(PCRE2_CONFIG_VERSION, version);
490  fprintf(fp, "\nPCRE2: %s", version);
491  }
492 #endif
493 
494 #ifdef USE_HCACHE
495  const char *backends = store_backend_list();
496  fprintf(fp, "\nstorage: %s", backends);
497  FREE(&backends);
498 #ifdef USE_HCACHE_COMPRESSION
499  backends = compress_list();
500  fprintf(fp, "\ncompression: %s", backends);
501  FREE(&backends);
502 #endif
503 #endif
504 
506  fprintf(fp, "\n\nConfigure options: %s\n", (char *) configure_options);
507 
508  rstrip_in_place((char *) cc_cflags);
509  fprintf(fp, "\nCompilation CFLAGS: %s\n", (char *) cc_cflags);
510 
511  fprintf(fp, "\n%s\n", _("Default options:"));
512  print_compile_options(comp_opts_default, fp);
513 
514  fprintf(fp, "\n%s\n", _("Compile options:"));
515  print_compile_options(comp_opts, fp);
516 
517 #ifdef DOMAIN
518  fprintf(fp, "DOMAIN=\"%s\"\n", DOMAIN);
519 #endif
520 #ifdef ISPELL
521  fprintf(fp, "ISPELL=\"%s\"\n", ISPELL);
522 #endif
523  fprintf(fp, "MAILPATH=\"%s\"\n", MAILPATH);
524 #ifdef MIXMASTER
525  fprintf(fp, "MIXMASTER=\"%s\"\n", MIXMASTER);
526 #endif
527  fprintf(fp, "PKGDATADIR=\"%s\"\n", PKGDATADIR);
528  fprintf(fp, "SENDMAIL=\"%s\"\n", SENDMAIL);
529  fprintf(fp, "SYSCONFDIR=\"%s\"\n", SYSCONFDIR);
530 
531  fprintf(fp, "\n");
532  fputs(_(ReachingUs), fp);
533 }
534 
541 void print_copyright(void)
542 {
543  puts(mutt_make_version());
544  puts(Copyright);
545  puts(_(Thanks));
546  puts(_(License));
547  puts(_(ReachingUs));
548 }
549 
565 bool feature_enabled(const char *name)
566 {
567  if (!name)
568  return false;
569  for (int i = 0; comp_opts_default[i].name; i++)
570  {
571  if (mutt_str_equal(name, comp_opts_default[i].name))
572  {
573  return true;
574  }
575  }
576  for (int i = 0; comp_opts[i].name; i++)
577  {
578  if (mutt_str_equal(name, comp_opts[i].name))
579  {
580  return comp_opts[i].enabled;
581  }
582  }
583  return false;
584 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
Convenience wrapper for the gui headers.
unsigned char configure_options[]
bool feature_enabled(const char *name)
Test if a compile-time feature is enabled.
Definition: version.c:565
List of built-in capabilities.
Definition: version.c:121
static int const char * fmt
Definition: acutest.h:488
void print_version(FILE *fp)
Print system and compile info to a file.
Definition: version.c:424
const char * name
Definition: version.c:123
#define _(a)
Definition: message.h:28
static const char * Copyright
Definition: version.c:72
#define ISPELL
Definition: mutt_config.c:69
Email Address Handling.
API for the header cache compression.
const char * store_backend_list(void)
Get a list of backend names.
Definition: store.c:84
static char * rstrip_in_place(char *s)
Strip a trailing carriage return.
Definition: version.c:403
static const char * ReachingUs
Definition: version.c:104
unsigned char cc_cflags[]
const char * compress_list(void)
Get a list of compression backend names.
Definition: compress.c:58
API for encryption/signing of emails.
Display version and copyright about NeoMutt.
const char * mutt_gpgme_print_version(void)
Get version of GPGME.
Definition: crypt_gpgme.c:4425
const char * mutt_idna_print_version(void)
Create an IDN version string.
Definition: idna.c:313
static const char * Thanks
Definition: version.c:84
const int SCREEN_WIDTH
Definition: version.c:67
#define FREE(x)
Definition: memory.h:40
static void print_compile_options(struct CompileOptions *co, FILE *fp)
Print a list of enabled/disabled features.
Definition: version.c:351
const char * store_compress_list(void)
const char * mutt_make_version(void)
Generate the NeoMutt version string.
Definition: muttlib.c:1460
Convenience wrapper for the library headers.
static const char * Notice
Definition: version.c:111
#define N_(a)
Definition: message.h:32
int enabled
0 Disabled, 1 Enabled, 2 Devel only
Definition: version.c:124
static const char * License
Definition: version.c:88
void print_copyright(void)
Print copyright message.
Definition: version.c:541