]> granicus.if.org Git - neomutt/blob - version.c
Convert mutt_attach_reply() to use buffer pool
[neomutt] / version.c
1 /**
2  * @file
3  * Display version and copyright about NeoMutt
4  *
5  * @authors
6  * Copyright (C) 1996-2007 Michael R. Elkins <me@mutt.org>
7  * Copyright (C) 1999-2007 Thomas Roessler <roessler@does-not-exist.org>
8  * Copyright (C) 2016-2017 Richard Russon <rich@flatcap.org>
9  *
10  * @copyright
11  * This program is free software: you can redistribute it and/or modify it under
12  * the terms of the GNU General Public License as published by the Free Software
13  * Foundation, either version 2 of the License, or (at your option) any later
14  * version.
15  *
16  * This program is distributed in the hope that it will be useful, but WITHOUT
17  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
19  * details.
20  *
21  * You should have received a copy of the GNU General Public License along with
22  * this program.  If not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /**
26  * @page version Display version and copyright about NeoMutt
27  *
28  * Display version and copyright about NeoMutt
29  */
30
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/mutt.h"
38 #include "address/lib.h"
39 #include "mutt_curses.h"
40 #include "ncrypt/crypt_gpgme.h"
41
42 /* #include "protos.h" */
43 const char *mutt_make_version(void);
44 /* #include "hcache/hcache.h" */
45 const char *mutt_hcache_backend_list(void);
46
47 const int SCREEN_WIDTH = 80;
48
49 extern unsigned char cc_version[];
50 extern unsigned char cc_cflags[];
51 extern unsigned char configure_options[];
52
53 static const char *Copyright =
54     "Copyright (C) 1996-2016 Michael R. Elkins <me@mutt.org>\n"
55     "Copyright (C) 1996-2002 Brandon Long <blong@fiction.net>\n"
56     "Copyright (C) 1997-2009 Thomas Roessler <roessler@does-not-exist.org>\n"
57     "Copyright (C) 1998-2005 Werner Koch <wk@isil.d.shuttle.de>\n"
58     "Copyright (C) 1999-2017 Brendan Cully <brendan@kublai.com>\n"
59     "Copyright (C) 1999-2002 Tommi Komulainen <Tommi.Komulainen@iki.fi>\n"
60     "Copyright (C) 2000-2004 Edmund Grimley Evans <edmundo@rano.org>\n"
61     "Copyright (C) 2006-2009 Rocco Rutte <pdmef@gmx.net>\n"
62     "Copyright (C) 2014-2019 Kevin J. McCarthy <kevin@8t8.us>\n"
63     "Copyright (C) 2015-2019 Richard Russon <rich@flatcap.org>\n";
64
65 static const char *Thanks =
66     N_("Many others not mentioned here contributed code, fixes,\n"
67        "and suggestions.\n");
68
69 static const char *License = N_(
70     "    This program is free software; you can redistribute it and/or modify\n"
71     "    it under the terms of the GNU General Public License as published by\n"
72     "    the Free Software Foundation; either version 2 of the License, or\n"
73     "    (at your option) any later version.\n"
74     "\n"
75     "    This program is distributed in the hope that it will be useful,\n"
76     "    but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
77     "    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
78     "    GNU General Public License for more details.\n"
79     "\n"
80     "    You should have received a copy of the GNU General Public License\n"
81     "    along with this program; if not, write to the Free Software\n"
82     "    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  "
83     "02110-1301, USA.\n");
84
85 static const char *ReachingUs =
86     N_("To learn more about NeoMutt, visit: https://neomutt.org\n"
87        "If you find a bug in NeoMutt, please raise an issue at:\n"
88        "    https://github.com/neomutt/neomutt/issues\n"
89        "or send an email to: <neomutt-devel@neomutt.org>\n");
90
91 // clang-format off
92 static const char *Notice =
93     N_("Copyright (C) 1996-2016 Michael R. Elkins and others.\n"
94        "NeoMutt comes with ABSOLUTELY NO WARRANTY; for details type 'neomutt -vv'.\n"
95        "NeoMutt is free software, and you are welcome to redistribute it\n"
96        "under certain conditions; type 'neomutt -vv' for details.\n");
97 // clang-format on
98
99 /**
100  * struct CompileOptions - List of built-in capabilities
101  */
102 struct CompileOptions
103 {
104   const char *name;
105   int enabled; // 0 Disabled, 1 Enabled, 2 Devel only
106 };
107
108 /* These are sorted by the display string */
109
110 static struct CompileOptions comp_opts_default[] = {
111   { "attach_headers_color", 1 },
112   { "compose_to_sender", 1 },
113   { "compress", 1 },
114   { "cond_date", 1 },
115   { "debug", 1 },
116   { "encrypt_to_self", 1 },
117   { "forgotten_attachments", 1 },
118   { "forwref", 1 },
119   { "ifdef", 1 },
120   { "imap", 1 },
121   { "index_color", 1 },
122   { "initials", 1 },
123   { "limit_current_thread", 1 },
124   { "multiple_fcc", 1 },
125   { "nested_if", 1 },
126   { "new_mail", 1 },
127   { "nntp", 1 },
128   { "pop", 1 },
129   { "progress", 1 },
130   { "quasi_delete", 1 },
131   { "regcomp", 1 },
132   { "reply_with_xorig", 1 },
133   { "sensible_browser", 1 },
134   { "sidebar", 1 },
135   { "skip_quoted", 1 },
136   { "smtp", 1 },
137   { "status_color", 1 },
138   { "timeout", 1 },
139   { "tls_sni", 1 },
140   { "trash", 1 },
141   { NULL, 0 },
142 };
143
144 static struct CompileOptions comp_opts[] = {
145 #ifdef USE_AUTOCRYPT
146   { "autocrypt", 1 },
147 #else
148   { "autocrypt", 0 },
149 #endif
150 #ifdef HAVE_BKGDSET
151   { "bkgdset", 1 },
152 #else
153   { "bkgdset", 0 },
154 #endif
155 #ifdef HAVE_COLOR
156   { "color", 1 },
157 #else
158   { "color", 0 },
159 #endif
160 #ifdef HAVE_CURS_SET
161   { "curs_set", 1 },
162 #else
163   { "curs_set", 0 },
164 #endif
165 #ifdef USE_FCNTL
166   { "fcntl", 1 },
167 #else
168   { "fcntl", 0 },
169 #endif
170 #ifdef USE_FLOCK
171   { "flock", 1 },
172 #else
173   { "flock", 0 },
174 #endif
175 #ifdef USE_FMEMOPEN
176   { "fmemopen", 1 },
177 #else
178   { "fmemopen", 0 },
179 #endif
180 #ifdef HAVE_FUTIMENS
181   { "futimens", 1 },
182 #else
183   { "futimens", 0 },
184 #endif
185 #ifdef HAVE_GETADDRINFO
186   { "getaddrinfo", 1 },
187 #else
188   { "getaddrinfo", 0 },
189 #endif
190 #ifdef USE_SSL_GNUTLS
191   { "gnutls", 1 },
192 #else
193   { "gnutls", 0 },
194 #endif
195 #ifdef CRYPT_BACKEND_GPGME
196   { "gpgme", 1 },
197 #else
198   { "gpgme", 0 },
199 #endif
200 #ifdef USE_GSS
201   { "gss", 1 },
202 #else
203   { "gss", 0 },
204 #endif
205 #ifdef USE_HCACHE
206   { "hcache", 1 },
207 #else
208   { "hcache", 0 },
209 #endif
210 #ifdef HOMESPOOL
211   { "homespool", 1 },
212 #else
213   { "homespool", 0 },
214 #endif
215 #ifdef HAVE_LIBIDN
216   { "idn", 1 },
217 #else
218   { "idn", 0 },
219 #endif
220 #ifdef USE_INOTIFY
221   { "inotify", 1 },
222 #else
223   { "inotify", 0 },
224 #endif
225 #ifdef LOCALES_HACK
226   { "locales_hack", 1 },
227 #else
228   { "locales_hack", 0 },
229 #endif
230 #ifdef USE_LUA
231   { "lua", 1 },
232 #else
233   { "lua", 0 },
234 #endif
235 #ifdef HAVE_META
236   { "meta", 1 },
237 #else
238   { "meta", 0 },
239 #endif
240 #ifdef MIXMASTER
241   { "mixmaster", 1 },
242 #else
243   { "mixmaster", 0 },
244 #endif
245 #ifdef ENABLE_NLS
246   { "nls", 1 },
247 #else
248   { "nls", 0 },
249 #endif
250 #ifdef USE_NOTMUCH
251   { "notmuch", 1 },
252 #else
253   { "notmuch", 0 },
254 #endif
255 #ifdef USE_SSL_OPENSSL
256   { "openssl", 1 },
257 #else
258   { "openssl", 0 },
259 #endif
260 #ifdef CRYPT_BACKEND_CLASSIC_PGP
261   { "pgp", 1 },
262 #else
263   { "pgp", 0 },
264 #endif
265 #ifdef USE_SASL
266   { "sasl", 1 },
267 #else
268   { "sasl", 0 },
269 #endif
270 #ifdef CRYPT_BACKEND_CLASSIC_SMIME
271   { "smime", 1 },
272 #else
273   { "smime", 0 },
274 #endif
275 #ifdef USE_SQLITE
276   { "sqlite", 1 },
277 #else
278   { "sqlite", 0 },
279 #endif
280 #ifdef HAVE_START_COLOR
281   { "start_color", 1 },
282 #else
283   { "start_color", 0 },
284 #endif
285 #ifdef SUN_ATTACHMENT
286   { "sun_attachment", 1 },
287 #else
288   { "sun_attachment", 0 },
289 #endif
290 #ifdef HAVE_TYPEAHEAD
291   { "typeahead", 1 },
292 #else
293   { "typeahead", 0 },
294 #endif
295   { NULL, 0 },
296 };
297
298 /**
299  * print_compile_options - Print a list of enabled/disabled features
300  * @param co Array of compile options
301  * @param fp file to write to
302  *
303  * Two lists are generated and passed to this function:
304  *
305  * One list which just uses the configure state of each feature.
306  * One list which just uses feature which are set to on directly in NeoMutt.
307  *
308  * The output is of the form: "+enabled_feature -disabled_feature" and is
309  * wrapped to SCREEN_WIDTH characters.
310  */
311 static void print_compile_options(struct CompileOptions *co, FILE *fp)
312 {
313   size_t used = 2;
314   bool tty = stdout ? isatty(fileno(stdout)) : false;
315
316   fprintf(fp, "  ");
317   for (int i = 0; co[i].name; i++)
318   {
319     const size_t len = strlen(co[i].name) + 2; /* +/- and a space */
320     if ((used + len) > SCREEN_WIDTH)
321     {
322       used = 2;
323       fprintf(fp, "\n  ");
324     }
325     used += len;
326     const char *fmt = "?%s ";
327     switch (co[i].enabled)
328     {
329       case 0: // Disabled
330         if (tty)
331           fmt = "\033[1;31m-%s\033[0m "; // Escape, red
332         else
333           fmt = "-%s ";
334         break;
335       case 1: // Enabled
336         if (tty)
337           fmt = "\033[1;32m+%s\033[0m "; // Escape, green
338         else
339           fmt = "+%s ";
340         break;
341       case 2: // Devel only
342         if (tty)
343           fmt = "\033[1;36m!%s\033[0m "; // Escape, cyan
344         else
345           fmt = "!%s ";
346         break;
347     }
348     fprintf(fp, fmt, co[i].name);
349   }
350   fprintf(fp, "\n");
351 }
352
353 /**
354  * rstrip_in_place - Strip a trailing carriage return
355  * @param s  String to be modified
356  * @retval ptr The modified string
357  *
358  * The string has its last carriage return set to NUL.
359  */
360 static char *rstrip_in_place(char *s)
361 {
362   if (!s)
363     return NULL;
364
365   char *p = &s[strlen(s)];
366   if (p == s)
367     return s;
368   p--;
369   while ((p >= s) && ((*p == '\n') || (*p == '\r')))
370     *p-- = '\0';
371   return s;
372 }
373
374 /**
375  * print_version - Print system and compile info to a file
376  * @param fp - file to print to
377  *
378  * Print information about the current system NeoMutt is running on.
379  * Also print a list of all the compile-time information.
380  */
381 void print_version(FILE *fp)
382 {
383   struct utsname uts;
384
385   fprintf(fp, "%s\n", mutt_make_version());
386   fprintf(fp, "%s\n", _(Notice));
387
388   uname(&uts);
389
390 #ifdef SCO
391   fprintf(fp, "System: SCO %s", uts.release);
392 #else
393   fprintf(fp, "System: %s %s", uts.sysname, uts.release);
394 #endif
395
396   fprintf(fp, " (%s)", uts.machine);
397
398 #ifdef NCURSES_VERSION
399   fprintf(fp, "\nncurses: %s (compiled with %s.%d)", curses_version(),
400           NCURSES_VERSION, NCURSES_VERSION_PATCH);
401 #elif defined(USE_SLANG_CURSES)
402   fprintf(fp, "\nslang: %s", SLANG_VERSION_STRING);
403 #endif
404
405 #ifdef _LIBICONV_VERSION
406   fprintf(fp, "\nlibiconv: %d.%d", _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 0xff);
407 #endif
408
409 #ifdef HAVE_LIBIDN
410   fprintf(fp, "\n%s", mutt_idna_print_version());
411 #endif
412
413 #ifdef CRYPT_BACKEND_GPGME
414   fprintf(fp, "\nGPGme: %s", mutt_gpgme_print_version());
415 #endif
416
417 #ifdef USE_HCACHE
418   const char *backends = mutt_hcache_backend_list();
419   fprintf(fp, "\nhcache backends: %s", backends);
420   FREE(&backends);
421 #endif
422
423   fputs("\n\nCompiler:\n", fp);
424   rstrip_in_place((char *) cc_version);
425   fprintf(fp, "%s\n", (char *) cc_version);
426
427   rstrip_in_place((char *) configure_options);
428   fprintf(fp, "\nConfigure options: %s\n", (char *) configure_options);
429
430   rstrip_in_place((char *) cc_cflags);
431   fprintf(fp, "\nCompilation CFLAGS: %s\n", (char *) cc_cflags);
432
433   fprintf(fp, "\n%s\n", _("Default options:"));
434   print_compile_options(comp_opts_default, fp);
435
436   fprintf(fp, "\n%s\n", _("Compile options:"));
437   print_compile_options(comp_opts, fp);
438
439 #ifdef DOMAIN
440   fprintf(fp, "DOMAIN=\"%s\"\n", DOMAIN);
441 #endif
442 #ifdef ISPELL
443   fprintf(fp, "ISPELL=\"%s\"\n", ISPELL);
444 #endif
445   fprintf(fp, "MAILPATH=\"%s\"\n", MAILPATH);
446 #ifdef MIXMASTER
447   fprintf(fp, "MIXMASTER=\"%s\"\n", MIXMASTER);
448 #endif
449   fprintf(fp, "PKGDATADIR=\"%s\"\n", PKGDATADIR);
450   fprintf(fp, "SENDMAIL=\"%s\"\n", SENDMAIL);
451   fprintf(fp, "SYSCONFDIR=\"%s\"\n", SYSCONFDIR);
452
453   fprintf(fp, "\n");
454   fputs(_(ReachingUs), fp);
455 }
456
457 /**
458  * print_copyright - Print copyright message
459  *
460  * Print the authors' copyright messages, the GPL license and some contact
461  * information for the NeoMutt project.
462  */
463 void print_copyright(void)
464 {
465   puts(mutt_make_version());
466   puts(Copyright);
467   puts(_(Thanks));
468   puts(_(License));
469   puts(_(ReachingUs));
470 }
471
472 /**
473  * feature_enabled - Test if a compile-time feature is enabled
474  * @param name  Compile-time symbol of the feature
475  * @retval true  Feature enabled
476  * @retval false Feature not enabled, or not compiled in
477  *
478  * Many of the larger features of neomutt can be disabled at compile time.
479  * They define a symbol and use ifdef's around their code.
480  * The symbols are mirrored in "CompileOptions comp_opts[]" in this
481  * file.
482  *
483  * This function checks if one of these symbols is present in the code.
484  *
485  * These symbols are also seen in the output of "neomutt -v".
486  */
487 bool feature_enabled(const char *name)
488 {
489   if (!name)
490     return false;
491   for (int i = 0; comp_opts_default[i].name; i++)
492   {
493     if (mutt_str_strcmp(name, comp_opts_default[i].name) == 0)
494     {
495       return true;
496     }
497   }
498   for (int i = 0; comp_opts[i].name; i++)
499   {
500     if (mutt_str_strcmp(name, comp_opts[i].name) == 0)
501     {
502       return comp_opts[i].enabled;
503     }
504   }
505   return false;
506 }