NeoMutt  2025-09-05-2-g4bf191
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
muttlib.c File Reference

Some miscellaneous functions. More...

#include "config.h"
#include <errno.h>
#include <limits.h>
#include <pwd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "muttlib.h"
#include "browser/lib.h"
#include "editor/lib.h"
#include "history/lib.h"
#include "imap/lib.h"
#include "ncrypt/lib.h"
#include "question/lib.h"
#include "globals.h"
#include "hook.h"
#include "mx.h"
#include "protos.h"
+ Include dependency graph for muttlib.c:

Go to the source code of this file.

Functions

void mutt_adv_mktemp (struct Buffer *buf)
 Create a temporary file.
 
void buf_expand_path_regex (struct Buffer *buf, bool regex)
 Create the canonical path (with regex char escaping)
 
void buf_expand_path (struct Buffer *buf)
 Create the canonical path.
 
char * mutt_gecos_name (char *dest, size_t destlen, struct passwd *pw)
 Lookup a user's real name in /etc/passwd.
 
bool mutt_needs_mailcap (struct Body *b)
 Does this type need a mailcap entry do display.
 
bool mutt_is_text_part (const struct Body *b)
 Is this part of an email in plain text?
 
void mutt_pretty_mailbox (char *buf, size_t buflen)
 Shorten a mailbox path using '~' or '='.
 
void buf_pretty_mailbox (struct Buffer *buf)
 Shorten a mailbox path using '~' or '='.
 
int mutt_check_overwrite (const char *attname, const char *path, struct Buffer *fname, enum SaveAttach *opt, char **directory)
 Ask the user if overwriting is necessary.
 
void mutt_save_path (char *buf, size_t buflen, const struct Address *addr)
 Turn an email address into a filename (for saving)
 
void buf_save_path (struct Buffer *dest, const struct Address *a)
 Make a safe filename from an email address.
 
void mutt_safe_path (struct Buffer *dest, const struct Address *a)
 Make a safe filename from an email address.
 
FILE * mutt_open_read (const char *path, pid_t *thepid)
 Run a command to read from.
 
int mutt_save_confirm (const char *s, struct stat *st)
 Ask the user to save.
 
void mutt_sleep (short s)
 Sleep for a while.
 
void mutt_encode_path (struct Buffer *buf, const char *src)
 Convert a path to 'us-ascii'.
 
int mutt_set_xdg_path (enum XdgType type, struct Buffer *buf)
 Find an XDG path or its fallback.
 
void mutt_get_parent_path (const char *path, char *buf, size_t buflen)
 Find the parent of a path (or mailbox)
 
void buf_sanitize_filename (struct Buffer *buf, const char *path, short slash)
 Replace unsafe characters in a filename.
 
int mutt_str_pretty_size (struct Buffer *buf, size_t num)
 Display an abbreviated size, like 3.4K.
 
void add_to_stailq (struct ListHead *head, const char *str)
 Add a string to a list.
 
void remove_from_stailq (struct ListHead *head, const char *str)
 Remove an item, matching a string, from a List.
 
void mutt_exit (int code)
 Leave NeoMutt NOW.
 

Variables

static const char * XdgEnvVars []
 Accepted XDG environment variables.
 
static const char * XdgDefaults []
 XDG default locations.
 

Detailed Description

Some miscellaneous functions.

Authors
  • Michael R. Elkins
  • Thomas Roessler
  • Richard Russon
  • Aleksa Sarai
  • Pietro Cerutti

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file muttlib.c.

Function Documentation

◆ mutt_adv_mktemp()

void mutt_adv_mktemp ( struct Buffer buf)

Create a temporary file.

Parameters
bufBuffer for the name

Accept a "suggestion" for file name. If that file exists, then construct one with unique name but keep any extension. This might fail, I guess.

Definition at line 83 of file muttlib.c.

84{
85 if (!(buf->data && (buf->data[0] != '\0')))
86 {
87 buf_mktemp(buf);
88 }
89 else
90 {
91 struct Buffer *prefix = buf_pool_get();
92 buf_strcpy(prefix, buf->data);
93 mutt_file_sanitize_filename(prefix->data, true);
94 const char *const c_tmp_dir = cs_subset_path(NeoMutt->sub, "tmp_dir");
95 buf_printf(buf, "%s/%s", NONULL(c_tmp_dir), buf_string(prefix));
96
97 struct stat st = { 0 };
98 if ((lstat(buf_string(buf), &st) == -1) && (errno == ENOENT))
99 goto out;
100
101 char *suffix = strchr(prefix->data, '.');
102 if (suffix)
103 {
104 *suffix = '\0';
105 suffix++;
106 }
107 buf_mktemp_pfx_sfx(buf, prefix->data, suffix);
108
109 out:
110 buf_pool_release(&prefix);
111 }
112}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:168
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:589
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:96
#define NONULL(x)
Definition: string2.h:36
String manipulation buffer.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:43
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:47
#define buf_mktemp(buf)
Definition: tmp.h:33
#define buf_mktemp_pfx_sfx(buf, prefix, suffix)
Definition: tmp.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buf_expand_path_regex()

void buf_expand_path_regex ( struct Buffer buf,
bool  regex 
)

Create the canonical path (with regex char escaping)

Parameters
bufBuffer with path
regexIf true, escape any regex characters
Note
The path is expanded in-place

Definition at line 121 of file muttlib.c.

122{
123 const char *s = NULL;
124 const char *tail = "";
125
126 bool recurse = false;
127
128 struct Buffer *p = buf_pool_get();
129 struct Buffer *q = buf_pool_get();
130 struct Buffer *tmp = buf_pool_get();
131
132 do
133 {
134 recurse = false;
135 s = buf_string(buf);
136
137 switch (*s)
138 {
139 case '~':
140 {
141 if ((s[1] == '/') || (s[1] == '\0'))
142 {
144 tail = s + 1;
145 }
146 else
147 {
148 char *t = strchr(s + 1, '/');
149 if (t)
150 *t = '\0';
151
152 struct passwd *pw = getpwnam(s + 1);
153 if (pw)
154 {
155 buf_strcpy(p, pw->pw_dir);
156 if (t)
157 {
158 *t = '/';
159 tail = t;
160 }
161 else
162 {
163 tail = "";
164 }
165 }
166 else
167 {
168 /* user not found! */
169 if (t)
170 *t = '/';
171 buf_reset(p);
172 tail = s;
173 }
174 }
175 break;
176 }
177
178 case '=':
179 case '+':
180 {
181 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
182 enum MailboxType mb_type = mx_path_probe(c_folder);
183
184 /* if folder = {host} or imap[s]://host/: don't append slash */
185 if ((mb_type == MUTT_IMAP) && ((c_folder[strlen(c_folder) - 1] == '}') ||
186 (c_folder[strlen(c_folder) - 1] == '/')))
187 {
188 buf_strcpy(p, c_folder);
189 }
190 else if (mb_type == MUTT_NOTMUCH)
191 {
192 buf_strcpy(p, c_folder);
193 }
194 else if (c_folder && (c_folder[strlen(c_folder) - 1] == '/'))
195 {
196 buf_strcpy(p, c_folder);
197 }
198 else
199 {
200 buf_printf(p, "%s/", NONULL(c_folder));
201 }
202
203 tail = s + 1;
204 break;
205 }
206
207 /* elm compatibility, @ expands alias to user name */
208
209 case '@':
210 {
211 struct AddressList *al = alias_lookup(s + 1);
212 if (al && !TAILQ_EMPTY(al))
213 {
214 struct Email *e = email_new();
215 e->env = mutt_env_new();
216 mutt_addrlist_copy(&e->env->from, al, false);
217 mutt_addrlist_copy(&e->env->to, al, false);
218
220 mutt_default_save(p, e);
221
222 email_free(&e);
223 /* Avoid infinite recursion if the resulting folder starts with '@' */
224 if (*p->data != '@')
225 recurse = true;
226
227 tail = "";
228 }
229 break;
230 }
231
232 case '>':
233 {
234 const char *const c_mbox = cs_subset_string(NeoMutt->sub, "mbox");
235 buf_strcpy(p, c_mbox);
236 tail = s + 1;
237 break;
238 }
239
240 case '<':
241 {
242 const char *const c_record = cs_subset_string(NeoMutt->sub, "record");
243 buf_strcpy(p, c_record);
244 tail = s + 1;
245 break;
246 }
247
248 case '!':
249 {
250 if (s[1] == '!')
251 {
253 tail = s + 2;
254 }
255 else
256 {
257 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
258 buf_strcpy(p, c_spool_file);
259 tail = s + 1;
260 }
261 break;
262 }
263
264 case '-':
265 {
267 tail = s + 1;
268 break;
269 }
270
271 case '^':
272 {
274 tail = s + 1;
275 break;
276 }
277
278 default:
279 {
280 buf_reset(p);
281 tail = s;
282 }
283 }
284
285 if (regex && *(buf_string(p)) && !recurse)
286 {
288 buf_printf(tmp, "%s%s", buf_string(q), tail);
289 }
290 else
291 {
292 buf_printf(tmp, "%s%s", buf_string(p), tail);
293 }
294
295 buf_copy(buf, tmp);
296 } while (recurse);
297
300 buf_pool_release(&tmp);
301
302 /* Rewrite IMAP path in canonical form - aids in string comparisons of
303 * folders. May possibly fail, in which case buf should be the same. */
304 if (imap_path_probe(buf_string(buf), NULL) == MUTT_IMAP)
305 imap_path_canon(buf);
306}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:765
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:277
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:76
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:601
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:337
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:291
MailboxType
Supported mailbox formats.
Definition: mailbox.h:41
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:51
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
struct Email * email_new(void)
Create a new Email.
Definition: email.c:77
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:46
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:46
int mutt_file_sanitize_regex(struct Buffer *dest, const char *src)
Escape any regex-magic characters in a string.
Definition: file.c:631
char * LastFolder
Previously selected mailbox.
Definition: globals.c:40
char * CurrentFolder
Currently selected mailbox.
Definition: globals.c:39
int imap_path_canon(struct Buffer *path)
Canonicalise a Mailbox path - Implements MxOps::path_canon() -.
Definition: imap.c:2363
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2349
void mutt_default_save(struct Buffer *path, struct Email *e)
Find the default save path for an email.
Definition: hook.c:779
#define PATH_MAX
Definition: mutt.h:42
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1326
#define TAILQ_EMPTY(head)
Definition: queue.h:778
The envelope/body of an email.
Definition: email.h:39
struct Envelope * env
Envelope information.
Definition: email.h:68
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
struct AddressList from
Email's 'From' list.
Definition: envelope.h:59
char * home_dir
User's home directory.
Definition: neomutt.h:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buf_expand_path()

void buf_expand_path ( struct Buffer buf)

Create the canonical path.

Parameters
bufBuffer with path
Note
The path is expanded in-place

Definition at line 314 of file muttlib.c.

315{
316 buf_expand_path_regex(buf, false);
317}
void buf_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:121
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_gecos_name()

char * mutt_gecos_name ( char *  dest,
size_t  destlen,
struct passwd *  pw 
)

Lookup a user's real name in /etc/passwd.

Parameters
destBuffer for the result
destlenLength of buffer
pwPasswd entry
Return values
ptrResult buffer on success

Extract the real name from /etc/passwd's GECOS field. When set, honor the regular expression in $gecos_mask, otherwise assume that the GECOS field is a comma-separated list. Replace "&" by a capitalized version of the user's login name.

Definition at line 331 of file muttlib.c.

332{
333 regmatch_t pat_match[1] = { 0 };
334 char *p = NULL;
335
336 if (!pw || !pw->pw_gecos)
337 return NULL;
338
339 memset(dest, 0, destlen);
340
341 const struct Regex *c_gecos_mask = cs_subset_regex(NeoMutt->sub, "gecos_mask");
342 if (mutt_regex_capture(c_gecos_mask, pw->pw_gecos, 1, pat_match))
343 {
344 mutt_str_copy(dest, pw->pw_gecos + pat_match[0].rm_so,
345 MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
346 }
347 else if ((p = strchr(pw->pw_gecos, ',')))
348 {
349 mutt_str_copy(dest, pw->pw_gecos, MIN(destlen, p - pw->pw_gecos + 1));
350 }
351 else
352 {
353 mutt_str_copy(dest, pw->pw_gecos, destlen);
354 }
355
356 size_t pwnl = strlen(pw->pw_name);
357
358 for (int idx = 0; dest[idx]; idx++)
359 {
360 if (dest[idx] == '&')
361 {
362 memmove(&dest[idx + pwnl], &dest[idx + 1],
363 MAX((ssize_t) (destlen - idx - pwnl - 1), 0));
364 memcpy(&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl));
365 dest[idx] = mutt_toupper(dest[idx]);
366 }
367 }
368
369 return dest;
370}
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:217
int mutt_toupper(int arg)
Wrapper for toupper(3)
Definition: ctype.c:139
#define MIN(a, b)
Definition: memory.h:37
#define MAX(a, b)
Definition: memory.h:36
bool mutt_regex_capture(const struct Regex *regex, const char *str, size_t nmatch, regmatch_t matches[])
Match a regex against a string, with provided options.
Definition: regex.c:597
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:580
Cached regular expression.
Definition: regex3.h:86
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_needs_mailcap()

bool mutt_needs_mailcap ( struct Body b)

Does this type need a mailcap entry do display.

Parameters
bAttachment body to be displayed
Return values
trueNeoMutt requires a mailcap entry to display
falseotherwise

Definition at line 378 of file muttlib.c.

379{
380 switch (b->type)
381 {
382 case TYPE_TEXT:
383 if (mutt_istr_equal("plain", b->subtype))
384 return false;
385 break;
386 case TYPE_APPLICATION:
388 return false;
390 return false;
391 break;
392
393 case TYPE_MULTIPART:
394 case TYPE_MESSAGE:
395 return false;
396 }
397
398 return true;
399}
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:610
SecurityFlags mutt_is_application_pgp(const struct Body *b)
Does the message use PGP?
Definition: crypt.c:549
@ TYPE_MESSAGE
Type: 'message/*'.
Definition: mime.h:35
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
@ TYPE_APPLICATION
Type: 'application/*'.
Definition: mime.h:33
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:671
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:96
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:97
#define WithCrypto
Definition: lib.h:122
char * subtype
content-type subtype
Definition: body.h:61
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_is_text_part()

bool mutt_is_text_part ( const struct Body b)

Is this part of an email in plain text?

Parameters
bPart of an email
Return values
truePart is in plain text

Definition at line 406 of file muttlib.c.

407{
408 int t = b->type;
409 char *s = b->subtype;
410
412 return false;
413
414 if (t == TYPE_TEXT)
415 return true;
416
417 if (t == TYPE_MESSAGE)
418 {
419 if (mutt_istr_equal("delivery-status", s))
420 return true;
421 }
422
423 if (((WithCrypto & APPLICATION_PGP) != 0) && (t == TYPE_APPLICATION))
424 {
425 if (mutt_istr_equal("pgp-keys", s))
426 return true;
427 }
428
429 return false;
430}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pretty_mailbox()

void mutt_pretty_mailbox ( char *  buf,
size_t  buflen 
)

Shorten a mailbox path using '~' or '='.

Parameters
bufBuffer containing string to shorten
buflenLength of buffer

Collapse the pathname using ~ or = when possible

Definition at line 439 of file muttlib.c.

440{
441 if (!buf)
442 return;
443
444 char *p = buf, *q = buf;
445 size_t len;
446 enum UrlScheme scheme;
447 char tmp[PATH_MAX] = { 0 };
448
449 scheme = url_check_scheme(buf);
450
451 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
452 if ((scheme == U_IMAP) || (scheme == U_IMAPS))
453 {
454 imap_pretty_mailbox(buf, buflen, c_folder);
455 return;
456 }
457
458 if (scheme == U_NOTMUCH)
459 return;
460
461 /* if buf is an url, only collapse path component */
462 if (scheme != U_UNKNOWN)
463 {
464 p = strchr(buf, ':') + 1;
465 if (mutt_strn_equal(p, "//", 2))
466 q = strchr(p + 2, '/');
467 if (!q)
468 q = strchr(p, '\0');
469 p = q;
470 }
471
472 /* cleanup path */
473 if (strstr(p, "//") || strstr(p, "/./"))
474 {
475 /* first attempt to collapse the pathname, this is more
476 * lightweight than realpath() and doesn't resolve links */
477 while (*p)
478 {
479 if ((p[0] == '/') && (p[1] == '/'))
480 {
481 *q++ = '/';
482 p += 2;
483 }
484 else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
485 {
486 *q++ = '/';
487 p += 3;
488 }
489 else
490 {
491 *q++ = *p++;
492 }
493 }
494 *q = '\0';
495 }
496 else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
497 realpath(p, tmp))
498 {
499 mutt_str_copy(p, tmp, buflen - (p - buf));
500 }
501
502 if ((len = mutt_str_startswith(buf, c_folder)) && (buf[len] == '/'))
503 {
504 *buf++ = '=';
505 memmove(buf, buf + len, mutt_str_len(buf + len) + 1);
506 }
507 else if ((len = mutt_str_startswith(buf, NeoMutt->home_dir)) && (buf[len] == '/'))
508 {
509 *buf++ = '~';
510 memmove(buf, buf + len - 1, mutt_str_len(buf + len - 1) + 1);
511 }
512}
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:583
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:426
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:231
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:497
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition: url.c:225
UrlScheme
All recognised Url types.
Definition: url.h:34
@ U_NOTMUCH
Url is notmuch://.
Definition: url.h:46
@ U_UNKNOWN
Url wasn't recognised.
Definition: url.h:35
@ U_FILE
Url is file://.
Definition: url.h:36
@ U_IMAP
Url is imap://.
Definition: url.h:39
@ U_IMAPS
Url is imaps://.
Definition: url.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buf_pretty_mailbox()

void buf_pretty_mailbox ( struct Buffer buf)

Shorten a mailbox path using '~' or '='.

Parameters
bufBuffer containing Mailbox name

Definition at line 518 of file muttlib.c.

519{
520 if (!buf || !buf->data)
521 return;
522 /* This reduces the size of the Buffer, so we can pass it through.
523 * We adjust the size just to make sure buf->data is not NULL though */
524 buf_alloc(buf, PATH_MAX);
525 mutt_pretty_mailbox(buf->data, buf->dsize);
526 buf_fix_dptr(buf);
527}
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:182
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:439
size_t dsize
Length of data.
Definition: buffer.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_check_overwrite()

int mutt_check_overwrite ( const char *  attname,
const char *  path,
struct Buffer fname,
enum SaveAttach opt,
char **  directory 
)

Ask the user if overwriting is necessary.

Parameters
[in]attnameAttachment name
[in]pathPath to save the file
[out]fnameBuffer for filename
[out]optSave option, see SaveAttach
[out]directoryDirectory to save under (OPTIONAL)
Return values
0Success
-1Abort
1Error

Definition at line 540 of file muttlib.c.

542{
543 struct stat st = { 0 };
544
545 buf_strcpy(fname, path);
546 if (access(buf_string(fname), F_OK) != 0)
547 return 0;
548 if (stat(buf_string(fname), &st) != 0)
549 return -1;
550 if (S_ISDIR(st.st_mode))
551 {
552 enum QuadOption ans = MUTT_NO;
553 if (directory)
554 {
555 switch (mw_multi_choice
556 /* L10N: Means "The path you specified as the destination file is a directory."
557 See the msgid "Save to file: " (alias.c, recvattach.c)
558 These three letters correspond to the choices in the string. */
559 (_("File is a directory, save under it: (y)es, (n)o, (a)ll?"), _("yna")))
560 {
561 case 3: /* all */
562 mutt_str_replace(directory, buf_string(fname));
563 break;
564 case 1: /* yes */
565 FREE(directory);
566 break;
567 case -1: /* abort */
568 FREE(directory);
569 return -1;
570 case 2: /* no */
571 FREE(directory);
572 return 1;
573 }
574 }
575 /* L10N: Means "The path you specified as the destination file is a directory."
576 See the msgid "Save to file: " (alias.c, recvattach.c) */
577 else if ((ans = query_yesorno(_("File is a directory, save under it?"), MUTT_YES)) != MUTT_YES)
578 return (ans == MUTT_NO) ? 1 : -1;
579
580 struct Buffer *tmp = buf_pool_get();
581 buf_strcpy(tmp, mutt_path_basename(NONULL(attname)));
582 struct FileCompletionData cdata = { false, NULL, NULL, NULL };
583 if ((mw_get_field(_("File under directory: "), tmp, MUTT_COMP_CLEAR,
584 HC_FILE, &CompleteFileOps, &cdata) != 0) ||
585 buf_is_empty(tmp))
586 {
587 buf_pool_release(&tmp);
588 return (-1);
589 }
590 buf_concat_path(fname, path, buf_string(tmp));
591 buf_pool_release(&tmp);
592 }
593
594 if ((*opt == MUTT_SAVE_NO_FLAGS) && (access(buf_string(fname), F_OK) == 0))
595 {
596 char buf[4096] = { 0 };
597 snprintf(buf, sizeof(buf), "%s - %s", buf_string(fname),
598 // L10N: Options for: File %s exists, (o)verwrite, (a)ppend, or (c)ancel?
599 _("File exists, (o)verwrite, (a)ppend, or (c)ancel?"));
600 switch (mw_multi_choice(buf, _("oac")))
601 {
602 case -1: /* abort */
603 return -1;
604 case 3: /* cancel */
605 return 1;
606
607 case 2: /* append */
608 *opt = MUTT_SAVE_APPEND;
609 break;
610 case 1: /* overwrite */
611 break;
612 }
613 }
614 return 0;
615}
const struct CompleteOps CompleteFileOps
Auto-Completion of Files.
Definition: complete.c:153
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
size_t buf_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:509
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition: window.c:273
int mw_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question -.
Definition: question.c:62
@ HC_FILE
Files.
Definition: lib.h:56
#define FREE(x)
Definition: memory.h:62
#define _(a)
Definition: message.h:28
const char * mutt_path_basename(const char *path)
Find the last component for a pathname.
Definition: path.c:282
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:281
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:57
@ MUTT_SAVE_APPEND
Append to existing file.
Definition: mutt_attach.h:59
@ MUTT_SAVE_NO_FLAGS
Overwrite existing file (the default)
Definition: mutt_attach.h:58
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition: quad.h:38
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:326
Input for the file completion function.
Definition: curs_lib.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_save_path()

void mutt_save_path ( char *  buf,
size_t  buflen,
const struct Address addr 
)

Turn an email address into a filename (for saving)

Parameters
bufBuffer for the result
buflenLength of buffer
addrEmail address to use

If the user hasn't set $save_address the name will be truncated to the '@' character.

Definition at line 626 of file muttlib.c.

627{
628 if (addr && addr->mailbox)
629 {
630 mutt_str_copy(buf, buf_string(addr->mailbox), buflen);
631 const bool c_save_address = cs_subset_bool(NeoMutt->sub, "save_address");
632 if (!c_save_address)
633 {
634 char *p = strpbrk(buf, "%@");
635 if (p)
636 *p = '\0';
637 }
638 mutt_str_lower(buf);
639 }
640 else
641 {
642 *buf = '\0';
643 }
644}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:47
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
Definition: string.c:314
struct Buffer * mailbox
Mailbox and host address.
Definition: address.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buf_save_path()

void buf_save_path ( struct Buffer dest,
const struct Address a 
)

Make a safe filename from an email address.

Parameters
destBuffer for the result
aAddress to use

Definition at line 651 of file muttlib.c.

652{
653 if (a && a->mailbox)
654 {
655 buf_copy(dest, a->mailbox);
656 const bool c_save_address = cs_subset_bool(NeoMutt->sub, "save_address");
657 if (!c_save_address)
658 {
659 char *p = strpbrk(dest->data, "%@");
660 if (p)
661 {
662 *p = '\0';
663 buf_fix_dptr(dest);
664 }
665 }
666 mutt_str_lower(dest->data);
667 }
668 else
669 {
670 buf_reset(dest);
671 }
672}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_safe_path()

void mutt_safe_path ( struct Buffer dest,
const struct Address a 
)

Make a safe filename from an email address.

Parameters
destBuffer for the result
aAddress to use

The filename will be stripped of '/', space, etc to make it safe.

Definition at line 681 of file muttlib.c.

682{
683 buf_save_path(dest, a);
684 for (char *p = dest->data; *p; p++)
685 if ((*p == '/') || mutt_isspace(*p) || !IsPrint((unsigned char) *p))
686 *p = '_';
687}
bool mutt_isspace(int arg)
Wrapper for isspace(3)
Definition: ctype.c:95
#define IsPrint(ch)
Definition: mbyte.h:40
void buf_save_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
Definition: muttlib.c:651
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_open_read()

FILE * mutt_open_read ( const char *  path,
pid_t *  thepid 
)

Run a command to read from.

Parameters
[in]pathPath to command
[out]thepidPID of the command
Return values
ptrFile containing output of command

This function allows the user to specify a command to read stdout from in place of a normal file. If the last character in the string is a pipe (|), then we assume it is a command to run instead of a normal file.

Definition at line 699 of file muttlib.c.

700{
701 FILE *fp = NULL;
702 struct stat st = { 0 };
703
704 size_t len = mutt_str_len(path);
705 if (len == 0)
706 {
707 return NULL;
708 }
709
710 if (path[len - 1] == '|')
711 {
712 /* read from a pipe */
713
714 char *p = mutt_str_dup(path);
715
716 p[len - 1] = 0;
717 mutt_endwin();
718 *thepid = filter_create(p, NULL, &fp, NULL, NeoMutt->env);
719 FREE(&p);
720 }
721 else
722 {
723 if (stat(path, &st) < 0)
724 return NULL;
725 if (S_ISDIR(st.st_mode))
726 {
727 errno = EINVAL;
728 return NULL;
729 }
730 fp = mutt_file_fopen(path, "r");
731 *thepid = -1;
732 }
733 return fp;
734}
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:152
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:138
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, char **envlist)
Set up filter program.
Definition: filter.c:209
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:254
char ** env
Private copy of the environment variables.
Definition: neomutt.h:55
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_save_confirm()

int mutt_save_confirm ( const char *  s,
struct stat *  st 
)

Ask the user to save.

Parameters
sSave location
stTimestamp
Return values
0OK to proceed
-1to abort
1to retry

Definition at line 744 of file muttlib.c.

745{
746 int rc = 0;
747
748 enum MailboxType type = mx_path_probe(s);
749
750 if (type == MUTT_POP)
751 {
752 mutt_error(_("Can't save message to POP mailbox"));
753 return 1;
754 }
755
756 if ((type != MUTT_MAILBOX_ERROR) && (type != MUTT_UNKNOWN) && (mx_access(s, W_OK) == 0))
757 {
758 const bool c_confirm_append = cs_subset_bool(NeoMutt->sub, "confirm_append");
759 if (c_confirm_append)
760 {
761 struct Buffer *tmp = buf_pool_get();
762 buf_printf(tmp, _("Append messages to %s?"), s);
764 NeoMutt->sub, "confirm_append");
765 if (ans == MUTT_NO)
766 rc = 1;
767 else if (ans == MUTT_ABORT)
768 rc = -1;
769 buf_pool_release(&tmp);
770 }
771 }
772
773 if (type == MUTT_NNTP)
774 {
775 mutt_error(_("Can't save message to news server"));
776 return 0;
777 }
778
779 if (stat(s, st) != -1)
780 {
781 if (type == MUTT_MAILBOX_ERROR)
782 {
783 mutt_error(_("%s is not a mailbox"), s);
784 return 1;
785 }
786 }
787 else if (type != MUTT_IMAP)
788 {
789 st->st_mtime = 0;
790 st->st_atime = 0;
791
792 /* pathname does not exist */
793 if (errno == ENOENT)
794 {
795 const bool c_confirm_create = cs_subset_bool(NeoMutt->sub, "confirm_create");
796 if (c_confirm_create)
797 {
798 struct Buffer *tmp = buf_pool_get();
799 buf_printf(tmp, _("Create %s?"), s);
801 NeoMutt->sub, "confirm_create");
802 if (ans == MUTT_NO)
803 rc = 1;
804 else if (ans == MUTT_ABORT)
805 rc = -1;
806 buf_pool_release(&tmp);
807 }
808
809 /* user confirmed with MUTT_YES or set `$confirm_create` */
810 if (rc == 0)
811 {
812 /* create dir recursively */
813 char *tmp_path = mutt_path_dirname(s);
814 if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
815 {
816 /* report failure & abort */
817 mutt_perror("%s", s);
818 FREE(&tmp_path);
819 return 1;
820 }
821 FREE(&tmp_path);
822 }
823 }
824 else
825 {
826 mutt_perror("%s", s);
827 return 1;
828 }
829 }
830
831 msgwin_clear_text(NULL);
832 return rc;
833}
@ MUTT_MAILBOX_ERROR
Error occurred examining Mailbox.
Definition: mailbox.h:43
@ MUTT_POP
'POP3' Mailbox type
Definition: mailbox.h:52
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition: mailbox.h:49
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition: mailbox.h:44
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:851
#define mutt_error(...)
Definition: logging2.h:93
#define mutt_perror(...)
Definition: logging2.h:94
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition: msgwin.c:519
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final '/'.
Definition: path.c:312
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
Definition: mx.c:170
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition: quad.h:37
enum QuadOption query_yesorno_help(const char *prompt, enum QuadOption def, struct ConfigSubset *sub, const char *name)
Ask the user a Yes/No question offering help.
Definition: question.c:354
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_sleep()

void mutt_sleep ( short  s)

Sleep for a while.

Parameters
sNumber of seconds to sleep

If the user config '$sleep_time' is larger, sleep that long instead.

Definition at line 841 of file muttlib.c.

842{
843 const short c_sleep_time = cs_subset_number(NeoMutt->sub, "sleep_time");
844 if (c_sleep_time > s)
845 sleep(c_sleep_time);
846 else if (s)
847 sleep(s);
848}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:143
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_encode_path()

void mutt_encode_path ( struct Buffer buf,
const char *  src 
)

Convert a path to 'us-ascii'.

Parameters
bufBuffer for the result
srcPath to convert (OPTIONAL)

If src is NULL, the path in buf will be converted in-place.

Definition at line 857 of file muttlib.c.

858{
859 char *p = mutt_str_dup(src);
860 int rc = mutt_ch_convert_string(&p, cc_charset(), "us-ascii", MUTT_ICONV_NO_FLAGS);
861 size_t len = buf_strcpy(buf, (rc == 0) ? NONULL(p) : NONULL(src));
862
863 /* convert the path to POSIX "Portable Filename Character Set" */
864 for (size_t i = 0; i < len; i++)
865 {
866 if (!mutt_isalnum(buf->data[i]) && !strchr("/.-_", buf->data[i]))
867 {
868 buf->data[i] = '_';
869 }
870 }
871 FREE(&p);
872}
const char * cc_charset(void)
Get the cached value of $charset.
Definition: config_cache.c:116
bool mutt_isalnum(int arg)
Wrapper for isalnum(3)
Definition: ctype.c:39
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:831
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:64
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_set_xdg_path()

int mutt_set_xdg_path ( enum XdgType  type,
struct Buffer buf 
)

Find an XDG path or its fallback.

Parameters
typeType of XDG variable, e.g. XDG_CONFIG_HOME
bufBuffer to save path
Return values
1An entry was found that actually exists on disk and 0 otherwise

Process an XDG environment variable or its fallback.

Definition at line 882 of file muttlib.c.

883{
884 const char *xdg_env = mutt_str_getenv(XdgEnvVars[type]);
885 char *xdg = xdg_env ? mutt_str_dup(xdg_env) : mutt_str_dup(XdgDefaults[type]);
886 char *x = xdg; /* mutt_str_sep() changes xdg, so free x instead later */
887 char *token = NULL;
888 int rc = 0;
889
890 while ((token = mutt_str_sep(&xdg, ":")))
891 {
892 if (buf_printf(buf, "%s/%s/neomuttrc", token, PACKAGE) < 0)
893 continue;
894 buf_expand_path(buf);
895 if (access(buf_string(buf), F_OK) == 0)
896 {
897 rc = 1;
898 break;
899 }
900
901 if (buf_printf(buf, "%s/%s/Muttrc", token, PACKAGE) < 0)
902 continue;
903 buf_expand_path(buf);
904 if (access(buf_string(buf), F_OK) == 0)
905 {
906 rc = 1;
907 break;
908 }
909 }
910
911 FREE(&x);
912 return rc;
913}
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:725
char * mutt_str_sep(char **stringp, const char *delim)
Find first occurrence of any of delim characters in *stringp.
Definition: string.c:187
static const char * XdgEnvVars[]
Accepted XDG environment variables.
Definition: muttlib.c:64
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:314
static const char * XdgDefaults[]
XDG default locations.
Definition: muttlib.c:70
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_parent_path()

void mutt_get_parent_path ( const char *  path,
char *  buf,
size_t  buflen 
)

Find the parent of a path (or mailbox)

Parameters
pathPath to use
bufBuffer for the result
buflenLength of buffer

Definition at line 921 of file muttlib.c.

922{
923 enum MailboxType mb_type = mx_path_probe(path);
924
925 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
926 if (mb_type == MUTT_IMAP)
927 {
928 imap_get_parent_path(path, buf, buflen);
929 }
930 else if (mb_type == MUTT_NOTMUCH)
931 {
932 mutt_str_copy(buf, c_folder, buflen);
933 }
934 else
935 {
936 mutt_str_copy(buf, path, buflen);
937 int n = mutt_str_len(buf);
938 if (n == 0)
939 return;
940
941 /* remove any final trailing '/' */
942 if (buf[n - 1] == '/')
943 buf[n - 1] = '\0';
944
945 /* Remove everything until the next slash */
946 for (n--; ((n >= 0) && (buf[n] != '/')); n--)
947 ; // do nothing
948
949 if (n > 0)
950 {
951 buf[n] = '\0';
952 }
953 else
954 {
955 buf[0] = '/';
956 buf[1] = '\0';
957 }
958 }
959}
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
Definition: util.c:163
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buf_sanitize_filename()

void buf_sanitize_filename ( struct Buffer buf,
const char *  path,
short  slash 
)

Replace unsafe characters in a filename.

Parameters
bufBuffer for the result
pathFilename to make safe
slashReplace '/' characters too

Definition at line 967 of file muttlib.c.

968{
969 if (!buf || !path)
970 return;
971
972 buf_reset(buf);
973
974 for (; *path; path++)
975 {
976 if ((slash && (*path == '/')) || !strchr(FilenameSafeChars, *path))
977 buf_addch(buf, '_');
978 else
979 buf_addch(buf, *path);
980 }
981}
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:241
const char FilenameSafeChars[]
Set of characters <=0x7F that are safe to use in filenames.
Definition: file.c:70
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_str_pretty_size()

int mutt_str_pretty_size ( struct Buffer buf,
size_t  num 
)

Display an abbreviated size, like 3.4K.

Parameters
[out]bufBuffer for the result
[in]numNumber to abbreviate
Return values
numBytes written to buf

Definition at line 989 of file muttlib.c.

990{
991 if (!buf)
992 return 0;
993
994 const bool c_size_show_bytes = cs_subset_bool(NeoMutt->sub, "size_show_bytes");
995 const bool c_size_show_fractions = cs_subset_bool(NeoMutt->sub, "size_show_fractions");
996 const bool c_size_show_mb = cs_subset_bool(NeoMutt->sub, "size_show_mb");
997 const bool c_size_units_on_left = cs_subset_bool(NeoMutt->sub, "size_units_on_left");
998
999 if (c_size_show_bytes && (num < 1024))
1000 {
1001 return buf_add_printf(buf, "%d", (int) num);
1002 }
1003
1004 if (num == 0)
1005 {
1006 return buf_addstr(buf, c_size_units_on_left ? "K0" : "0K");
1007 }
1008
1009 if (c_size_show_fractions && (num < 10189)) /* 0.1K - 9.9K */
1010 {
1011 return buf_add_printf(buf, c_size_units_on_left ? "K%3.1f" : "%3.1fK",
1012 (num < 103) ? 0.1 : (num / 1024.0));
1013 }
1014
1015 if (!c_size_show_mb || (num < 1023949)) /* 10K - 999K */
1016 {
1017 /* 51 is magic which causes 10189/10240 to be rounded up to 10 */
1018 return buf_add_printf(buf, c_size_units_on_left ? ("K%zu") : ("%zuK"), (num + 51) / 1024);
1019 }
1020
1021 if (c_size_show_fractions && (num < 10433332)) /* 1.0M - 9.9M */
1022 {
1023 return buf_add_printf(buf, c_size_units_on_left ? "M%3.1f" : "%3.1fM", num / 1048576.0);
1024 }
1025
1026 /* 10M+ -- (10433332 + 52428) / 1048576 = 10 */
1027 return buf_add_printf(buf, c_size_units_on_left ? ("M%zu") : ("%zuM"),
1028 (num + 52428) / 1048576);
1029}
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:204
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_to_stailq()

void add_to_stailq ( struct ListHead *  head,
const char *  str 
)

Add a string to a list.

Parameters
headString list
strString to add
Note
Duplicate or empty strings will not be added

Definition at line 1038 of file muttlib.c.

1039{
1040 /* don't add a NULL or empty string to the list */
1041 if (!str || (*str == '\0'))
1042 return;
1043
1044 /* check to make sure the item is not already on this list */
1045 struct ListNode *np = NULL;
1046 STAILQ_FOREACH(np, head, entries)
1047 {
1048 if (mutt_istr_equal(str, np->data))
1049 {
1050 return;
1051 }
1052 }
1054}
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:65
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:390
A List node for strings.
Definition: list.h:37
char * data
String.
Definition: list.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_from_stailq()

void remove_from_stailq ( struct ListHead *  head,
const char *  str 
)

Remove an item, matching a string, from a List.

Parameters
headHead of the List
strString to match
Note
The string comparison is case-insensitive

Definition at line 1063 of file muttlib.c.

1064{
1065 if (mutt_str_equal("*", str))
1066 {
1067 mutt_list_free(head); /* "unCMD *" means delete all current entries */
1068 }
1069 else
1070 {
1071 struct ListNode *np = NULL, *tmp = NULL;
1072 STAILQ_FOREACH_SAFE(np, head, entries, tmp)
1073 {
1074 if (mutt_istr_equal(str, np->data))
1075 {
1076 STAILQ_REMOVE(head, np, ListNode, entries);
1077 FREE(&np->data);
1078 FREE(&np);
1079 break;
1080 }
1081 }
1082 }
1083}
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:659
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:441
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:400
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_exit()

void mutt_exit ( int  code)

Leave NeoMutt NOW.

Parameters
codeValue to return to the calling environment

Definition at line 1089 of file muttlib.c.

1090{
1091 mutt_endwin();
1092#ifdef USE_DEBUG_BACKTRACE
1093 if (code != 0)
1095#endif
1096 exit(code);
1097}
void show_backtrace(void)
Log the program's call stack.
Definition: backtrace.c:40
+ Here is the call graph for this function:

Variable Documentation

◆ XdgEnvVars

const char* XdgEnvVars[]
static
Initial value:
= {
[XDG_CONFIG_HOME] = "XDG_CONFIG_HOME",
[XDG_CONFIG_DIRS] = "XDG_CONFIG_DIRS",
}
@ XDG_CONFIG_HOME
XDG home dir: ~/.config.
Definition: protos.h:45
@ XDG_CONFIG_DIRS
XDG system dir: /etc/xdg.
Definition: protos.h:46

Accepted XDG environment variables.

Definition at line 64 of file muttlib.c.

◆ XdgDefaults

const char* XdgDefaults[]
static
Initial value:
= {
[XDG_CONFIG_HOME] = "~/.config",
[XDG_CONFIG_DIRS] = "/etc/xdg",
}

XDG default locations.

Definition at line 70 of file muttlib.c.