NeoMutt  2025-01-09-41-g086358
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
muttlib.c File Reference

Some miscellaneous functions. More...

#include "config.h"
#include <ctype.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.
 
const char * mutt_make_version (void)
 Generate the NeoMutt version string.
 
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.
 
void mutt_str_pretty_size (char *buf, size_t buflen, 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.
 

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 84 of file muttlib.c.

85{
86 if (!(buf->data && (buf->data[0] != '\0')))
87 {
88 buf_mktemp(buf);
89 }
90 else
91 {
92 struct Buffer *prefix = buf_pool_get();
93 buf_strcpy(prefix, buf->data);
94 mutt_file_sanitize_filename(prefix->data, true);
95 const char *const c_tmp_dir = cs_subset_path(NeoMutt->sub, "tmp_dir");
96 buf_printf(buf, "%s/%s", NONULL(c_tmp_dir), buf_string(prefix));
97
98 struct stat st = { 0 };
99 if ((lstat(buf_string(buf), &st) == -1) && (errno == ENOENT))
100 goto out;
101
102 char *suffix = strchr(prefix->data, '.');
103 if (suffix)
104 {
105 *suffix = '\0';
106 suffix++;
107 }
108 buf_mktemp_pfx_sfx(buf, prefix->data, suffix);
109
110 out:
111 buf_pool_release(&prefix);
112 }
113}
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:37
String manipulation buffer.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
#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 122 of file muttlib.c.

123{
124 const char *s = NULL;
125 const char *tail = "";
126
127 bool recurse = false;
128
129 struct Buffer *p = buf_pool_get();
130 struct Buffer *q = buf_pool_get();
131 struct Buffer *tmp = buf_pool_get();
132
133 do
134 {
135 recurse = false;
136 s = buf_string(buf);
137
138 switch (*s)
139 {
140 case '~':
141 {
142 if ((s[1] == '/') || (s[1] == '\0'))
143 {
145 tail = s + 1;
146 }
147 else
148 {
149 char *t = strchr(s + 1, '/');
150 if (t)
151 *t = '\0';
152
153 struct passwd *pw = getpwnam(s + 1);
154 if (pw)
155 {
156 buf_strcpy(p, pw->pw_dir);
157 if (t)
158 {
159 *t = '/';
160 tail = t;
161 }
162 else
163 {
164 tail = "";
165 }
166 }
167 else
168 {
169 /* user not found! */
170 if (t)
171 *t = '/';
172 buf_reset(p);
173 tail = s;
174 }
175 }
176 break;
177 }
178
179 case '=':
180 case '+':
181 {
182 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
183 enum MailboxType mb_type = mx_path_probe(c_folder);
184
185 /* if folder = {host} or imap[s]://host/: don't append slash */
186 if ((mb_type == MUTT_IMAP) && ((c_folder[strlen(c_folder) - 1] == '}') ||
187 (c_folder[strlen(c_folder) - 1] == '/')))
188 {
189 buf_strcpy(p, c_folder);
190 }
191 else if (mb_type == MUTT_NOTMUCH)
192 {
193 buf_strcpy(p, c_folder);
194 }
195 else if (c_folder && (c_folder[strlen(c_folder) - 1] == '/'))
196 {
197 buf_strcpy(p, c_folder);
198 }
199 else
200 {
201 buf_printf(p, "%s/", NONULL(c_folder));
202 }
203
204 tail = s + 1;
205 break;
206 }
207
208 /* elm compatibility, @ expands alias to user name */
209
210 case '@':
211 {
212 struct AddressList *al = alias_lookup(s + 1);
213 if (al && !TAILQ_EMPTY(al))
214 {
215 struct Email *e = email_new();
216 e->env = mutt_env_new();
217 mutt_addrlist_copy(&e->env->from, al, false);
218 mutt_addrlist_copy(&e->env->to, al, false);
219
221 mutt_default_save(p, e);
222
223 email_free(&e);
224 /* Avoid infinite recursion if the resulting folder starts with '@' */
225 if (*p->data != '@')
226 recurse = true;
227
228 tail = "";
229 }
230 break;
231 }
232
233 case '>':
234 {
235 const char *const c_mbox = cs_subset_string(NeoMutt->sub, "mbox");
236 buf_strcpy(p, c_mbox);
237 tail = s + 1;
238 break;
239 }
240
241 case '<':
242 {
243 const char *const c_record = cs_subset_string(NeoMutt->sub, "record");
244 buf_strcpy(p, c_record);
245 tail = s + 1;
246 break;
247 }
248
249 case '!':
250 {
251 if (s[1] == '!')
252 {
254 tail = s + 2;
255 }
256 else
257 {
258 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
259 buf_strcpy(p, c_spool_file);
260 tail = s + 1;
261 }
262 break;
263 }
264
265 case '-':
266 {
268 tail = s + 1;
269 break;
270 }
271
272 case '^':
273 {
275 tail = s + 1;
276 break;
277 }
278
279 default:
280 {
281 buf_reset(p);
282 tail = s;
283 }
284 }
285
286 if (regex && *(buf_string(p)) && !recurse)
287 {
289 buf_printf(tmp, "%s%s", buf_string(q), tail);
290 }
291 else
292 {
293 buf_printf(tmp, "%s%s", buf_string(p), tail);
294 }
295
296 buf_copy(buf, tmp);
297 } while (recurse);
298
301 buf_pool_release(&tmp);
302
303 /* Rewrite IMAP path in canonical form - aids in string comparisons of
304 * folders. May possibly fail, in which case buf should be the same. */
305 if (imap_path_probe(buf_string(buf), NULL) == MUTT_IMAP)
306 imap_path_canon(buf);
307}
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
char * HomeDir
User's home directory.
Definition: globals.c:37
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:43
char * CurrentFolder
Currently selected mailbox.
Definition: globals.c:42
int imap_path_canon(struct Buffer *path)
Canonicalise a Mailbox path - Implements MxOps::path_canon() -.
Definition: imap.c:2358
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2344
void mutt_default_save(struct Buffer *path, struct Email *e)
Find the default save path for an email.
Definition: hook.c:777
#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:1325
#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
+ 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 315 of file muttlib.c.

316{
317 buf_expand_path_regex(buf, false);
318}
void buf_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:122
+ 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 332 of file muttlib.c.

333{
334 regmatch_t pat_match[1] = { 0 };
335 char *p = NULL;
336
337 if (!pw || !pw->pw_gecos)
338 return NULL;
339
340 memset(dest, 0, destlen);
341
342 const struct Regex *c_gecos_mask = cs_subset_regex(NeoMutt->sub, "gecos_mask");
343 if (mutt_regex_capture(c_gecos_mask, pw->pw_gecos, 1, pat_match))
344 {
345 mutt_str_copy(dest, pw->pw_gecos + pat_match[0].rm_so,
346 MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
347 }
348 else if ((p = strchr(pw->pw_gecos, ',')))
349 {
350 mutt_str_copy(dest, pw->pw_gecos, MIN(destlen, p - pw->pw_gecos + 1));
351 }
352 else
353 {
354 mutt_str_copy(dest, pw->pw_gecos, destlen);
355 }
356
357 size_t pwnl = strlen(pw->pw_name);
358
359 for (int idx = 0; dest[idx]; idx++)
360 {
361 if (dest[idx] == '&')
362 {
363 memmove(&dest[idx + pwnl], &dest[idx + 1],
364 MAX((ssize_t) (destlen - idx - pwnl - 1), 0));
365 memcpy(&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl));
366 dest[idx] = toupper((unsigned char) dest[idx]);
367 }
368 }
369
370 return dest;
371}
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:217
#define MIN(a, b)
Definition: memory.h:32
#define MAX(a, b)
Definition: memory.h:31
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:581
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 379 of file muttlib.c.

380{
381 switch (b->type)
382 {
383 case TYPE_TEXT:
384 if (mutt_istr_equal("plain", b->subtype))
385 return false;
386 break;
387 case TYPE_APPLICATION:
389 return false;
391 return false;
392 break;
393
394 case TYPE_MULTIPART:
395 case TYPE_MESSAGE:
396 return false;
397 }
398
399 return true;
400}
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:609
SecurityFlags mutt_is_application_pgp(const struct Body *b)
Does the message use PGP?
Definition: crypt.c:548
@ 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:672
#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 407 of file muttlib.c.

408{
409 int t = b->type;
410 char *s = b->subtype;
411
413 return false;
414
415 if (t == TYPE_TEXT)
416 return true;
417
418 if (t == TYPE_MESSAGE)
419 {
420 if (mutt_istr_equal("delivery-status", s))
421 return true;
422 }
423
424 if (((WithCrypto & APPLICATION_PGP) != 0) && (t == TYPE_APPLICATION))
425 {
426 if (mutt_istr_equal("pgp-keys", s))
427 return true;
428 }
429
430 return false;
431}
+ 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 440 of file muttlib.c.

441{
442 if (!buf)
443 return;
444
445 char *p = buf, *q = buf;
446 size_t len;
447 enum UrlScheme scheme;
448 char tmp[PATH_MAX] = { 0 };
449
450 scheme = url_check_scheme(buf);
451
452 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
453 if ((scheme == U_IMAP) || (scheme == U_IMAPS))
454 {
455 imap_pretty_mailbox(buf, buflen, c_folder);
456 return;
457 }
458
459 if (scheme == U_NOTMUCH)
460 return;
461
462 /* if buf is an url, only collapse path component */
463 if (scheme != U_UNKNOWN)
464 {
465 p = strchr(buf, ':') + 1;
466 if (mutt_strn_equal(p, "//", 2))
467 q = strchr(p + 2, '/');
468 if (!q)
469 q = strchr(p, '\0');
470 p = q;
471 }
472
473 /* cleanup path */
474 if (strstr(p, "//") || strstr(p, "/./"))
475 {
476 /* first attempt to collapse the pathname, this is more
477 * lightweight than realpath() and doesn't resolve links */
478 while (*p)
479 {
480 if ((p[0] == '/') && (p[1] == '/'))
481 {
482 *q++ = '/';
483 p += 2;
484 }
485 else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
486 {
487 *q++ = '/';
488 p += 3;
489 }
490 else
491 {
492 *q++ = *p++;
493 }
494 }
495 *q = '\0';
496 }
497 else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
498 realpath(p, tmp))
499 {
500 mutt_str_copy(p, tmp, buflen - (p - buf));
501 }
502
503 if ((len = mutt_str_startswith(buf, c_folder)) && (buf[len] == '/'))
504 {
505 *buf++ = '=';
506 memmove(buf, buf + len, mutt_str_len(buf + len) + 1);
507 }
508 else if ((len = mutt_str_startswith(buf, HomeDir)) && (buf[len] == '/'))
509 {
510 *buf++ = '~';
511 memmove(buf, buf + len - 1, mutt_str_len(buf + len - 1) + 1);
512 }
513}
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:584
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:425
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:230
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:496
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition: url.c:226
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 519 of file muttlib.c.

520{
521 if (!buf || !buf->data)
522 return;
523 /* This reduces the size of the Buffer, so we can pass it through.
524 * We adjust the size just to make sure buf->data is not NULL though */
525 buf_alloc(buf, PATH_MAX);
526 mutt_pretty_mailbox(buf->data, buf->dsize);
527 buf_fix_dptr(buf);
528}
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:440
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 541 of file muttlib.c.

543{
544 struct stat st = { 0 };
545
546 buf_strcpy(fname, path);
547 if (access(buf_string(fname), F_OK) != 0)
548 return 0;
549 if (stat(buf_string(fname), &st) != 0)
550 return -1;
551 if (S_ISDIR(st.st_mode))
552 {
553 enum QuadOption ans = MUTT_NO;
554 if (directory)
555 {
556 switch (mw_multi_choice
557 /* L10N: Means "The path you specified as the destination file is a directory."
558 See the msgid "Save to file: " (alias.c, recvattach.c)
559 These three letters correspond to the choices in the string. */
560 (_("File is a directory, save under it: (y)es, (n)o, (a)ll?"), _("yna")))
561 {
562 case 3: /* all */
563 mutt_str_replace(directory, buf_string(fname));
564 break;
565 case 1: /* yes */
566 FREE(directory);
567 break;
568 case -1: /* abort */
569 FREE(directory);
570 return -1;
571 case 2: /* no */
572 FREE(directory);
573 return 1;
574 }
575 }
576 /* L10N: Means "The path you specified as the destination file is a directory."
577 See the msgid "Save to file: " (alias.c, recvattach.c) */
578 else if ((ans = query_yesorno(_("File is a directory, save under it?"), MUTT_YES)) != MUTT_YES)
579 return (ans == MUTT_NO) ? 1 : -1;
580
581 struct Buffer *tmp = buf_pool_get();
582 buf_strcpy(tmp, mutt_path_basename(NONULL(attname)));
583 struct FileCompletionData cdata = { false, NULL, NULL, NULL };
584 if ((mw_get_field(_("File under directory: "), tmp, MUTT_COMP_CLEAR,
585 HC_FILE, &CompleteFileOps, &cdata) != 0) ||
586 buf_is_empty(tmp))
587 {
588 buf_pool_release(&tmp);
589 return (-1);
590 }
591 buf_concat_path(fname, path, buf_string(tmp));
592 buf_pool_release(&tmp);
593 }
594
595 if ((*opt == MUTT_SAVE_NO_FLAGS) && (access(buf_string(fname), F_OK) == 0))
596 {
597 char buf[4096] = { 0 };
598 snprintf(buf, sizeof(buf), "%s - %s", buf_string(fname),
599 // L10N: Options for: File %s exists, (o)verwrite, (a)ppend, or (c)ancel?
600 _("File exists, (o)verwrite, (a)ppend, or (c)ancel?"));
601 switch (mw_multi_choice(buf, _("oac")))
602 {
603 case -1: /* abort */
604 return -1;
605 case 3: /* cancel */
606 return 1;
607
608 case 2: /* append */
609 *opt = MUTT_SAVE_APPEND;
610 break;
611 case 1: /* overwrite */
612 break;
613 }
614 }
615 return 0;
616}
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:63
@ HC_FILE
Files.
Definition: lib.h:56
#define FREE(x)
Definition: memory.h:55
#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:280
#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:327
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 627 of file muttlib.c.

628{
629 if (addr && addr->mailbox)
630 {
631 mutt_str_copy(buf, buf_string(addr->mailbox), buflen);
632 const bool c_save_address = cs_subset_bool(NeoMutt->sub, "save_address");
633 if (!c_save_address)
634 {
635 char *p = strpbrk(buf, "%@");
636 if (p)
637 *p = '\0';
638 }
639 mutt_str_lower(buf);
640 }
641 else
642 {
643 *buf = '\0';
644 }
645}
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:313
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 652 of file muttlib.c.

653{
654 if (a && a->mailbox)
655 {
656 buf_copy(dest, a->mailbox);
657 const bool c_save_address = cs_subset_bool(NeoMutt->sub, "save_address");
658 if (!c_save_address)
659 {
660 char *p = strpbrk(dest->data, "%@");
661 if (p)
662 {
663 *p = '\0';
664 buf_fix_dptr(dest);
665 }
666 }
667 mutt_str_lower(dest->data);
668 }
669 else
670 {
671 buf_reset(dest);
672 }
673}
+ 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 682 of file muttlib.c.

683{
684 buf_save_path(dest, a);
685 for (char *p = dest->data; *p; p++)
686 if ((*p == '/') || isspace(*p) || !IsPrint((unsigned char) *p))
687 *p = '_';
688}
#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:652
+ 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 700 of file muttlib.c.

701{
702 FILE *fp = NULL;
703 struct stat st = { 0 };
704
705 size_t len = mutt_str_len(path);
706 if (len == 0)
707 {
708 return NULL;
709 }
710
711 if (path[len - 1] == '|')
712 {
713 /* read from a pipe */
714
715 char *p = mutt_str_dup(path);
716
717 p[len - 1] = 0;
718 mutt_endwin();
719 *thepid = filter_create(p, NULL, &fp, NULL, EnvList);
720 FREE(&p);
721 }
722 else
723 {
724 if (stat(path, &st) < 0)
725 return NULL;
726 if (S_ISDIR(st.st_mode))
727 {
728 errno = EINVAL;
729 return NULL;
730 }
731 fp = mutt_file_fopen(path, "r");
732 *thepid = -1;
733 }
734 return fp;
735}
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:151
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:138
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:75
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:253
+ 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 745 of file muttlib.c.

746{
747 int rc = 0;
748
749 enum MailboxType type = mx_path_probe(s);
750
751 if (type == MUTT_POP)
752 {
753 mutt_error(_("Can't save message to POP mailbox"));
754 return 1;
755 }
756
757 if ((type != MUTT_MAILBOX_ERROR) && (type != MUTT_UNKNOWN) && (mx_access(s, W_OK) == 0))
758 {
759 const bool c_confirm_append = cs_subset_bool(NeoMutt->sub, "confirm_append");
760 if (c_confirm_append)
761 {
762 struct Buffer *tmp = buf_pool_get();
763 buf_printf(tmp, _("Append messages to %s?"), s);
765 NeoMutt->sub, "confirm_append");
766 if (ans == MUTT_NO)
767 rc = 1;
768 else if (ans == MUTT_ABORT)
769 rc = -1;
770 buf_pool_release(&tmp);
771 }
772 }
773
774 if (type == MUTT_NNTP)
775 {
776 mutt_error(_("Can't save message to news server"));
777 return 0;
778 }
779
780 if (stat(s, st) != -1)
781 {
782 if (type == MUTT_MAILBOX_ERROR)
783 {
784 mutt_error(_("%s is not a mailbox"), s);
785 return 1;
786 }
787 }
788 else if (type != MUTT_IMAP)
789 {
790 st->st_mtime = 0;
791 st->st_atime = 0;
792
793 /* pathname does not exist */
794 if (errno == ENOENT)
795 {
796 const bool c_confirm_create = cs_subset_bool(NeoMutt->sub, "confirm_create");
797 if (c_confirm_create)
798 {
799 struct Buffer *tmp = buf_pool_get();
800 buf_printf(tmp, _("Create %s?"), s);
802 NeoMutt->sub, "confirm_create");
803 if (ans == MUTT_NO)
804 rc = 1;
805 else if (ans == MUTT_ABORT)
806 rc = -1;
807 buf_pool_release(&tmp);
808 }
809
810 /* user confirmed with MUTT_YES or set `$confirm_create` */
811 if (rc == 0)
812 {
813 /* create dir recursively */
814 char *tmp_path = mutt_path_dirname(s);
815 if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
816 {
817 /* report failure & abort */
818 mutt_perror("%s", s);
819 FREE(&tmp_path);
820 return 1;
821 }
822 FREE(&tmp_path);
823 }
824 }
825 else
826 {
827 mutt_perror("%s", s);
828 return 1;
829 }
830 }
831
832 msgwin_clear_text(NULL);
833 return rc;
834}
@ 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:92
#define mutt_perror(...)
Definition: logging2.h:93
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:355
+ 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 842 of file muttlib.c.

843{
844 const short c_sleep_time = cs_subset_number(NeoMutt->sub, "sleep_time");
845 if (c_sleep_time > s)
846 sleep(c_sleep_time);
847 else if (s)
848 sleep(s);
849}
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_make_version()

const char * mutt_make_version ( void  )

Generate the NeoMutt version string.

Return values
ptrVersion string
Note
This returns a pointer to a static buffer

Definition at line 857 of file muttlib.c.

858{
859 static char vstring[256];
860 snprintf(vstring, sizeof(vstring), "NeoMutt %s%s", PACKAGE_VERSION, GitVer);
861 return vstring;
862}
const char * GitVer
+ 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 871 of file muttlib.c.

872{
873 char *p = mutt_str_dup(src);
874 int rc = mutt_ch_convert_string(&p, cc_charset(), "us-ascii", MUTT_ICONV_NO_FLAGS);
875 size_t len = buf_strcpy(buf, (rc == 0) ? NONULL(p) : NONULL(src));
876
877 /* convert the path to POSIX "Portable Filename Character Set" */
878 for (size_t i = 0; i < len; i++)
879 {
880 if (!isalnum(buf->data[i]) && !strchr("/.-_", buf->data[i]))
881 {
882 buf->data[i] = '_';
883 }
884 }
885 FREE(&p);
886}
const char * cc_charset(void)
Get the cached value of $charset.
Definition: config_cache.c:116
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 896 of file muttlib.c.

897{
898 const char *xdg_env = mutt_str_getenv(XdgEnvVars[type]);
899 char *xdg = xdg_env ? mutt_str_dup(xdg_env) : mutt_str_dup(XdgDefaults[type]);
900 char *x = xdg; /* mutt_str_sep() changes xdg, so free x instead later */
901 char *token = NULL;
902 int rc = 0;
903
904 while ((token = mutt_str_sep(&xdg, ":")))
905 {
906 if (buf_printf(buf, "%s/%s/neomuttrc", token, PACKAGE) < 0)
907 continue;
908 buf_expand_path(buf);
909 if (access(buf_string(buf), F_OK) == 0)
910 {
911 rc = 1;
912 break;
913 }
914
915 if (buf_printf(buf, "%s/%s/Muttrc", token, PACKAGE) < 0)
916 continue;
917 buf_expand_path(buf);
918 if (access(buf_string(buf), F_OK) == 0)
919 {
920 rc = 1;
921 break;
922 }
923 }
924
925 FREE(&x);
926 return rc;
927}
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:726
char * mutt_str_sep(char **stringp, const char *delim)
Find first occurrence of any of delim characters in *stringp.
Definition: string.c:186
static const char * XdgEnvVars[]
Accepted XDG environment variables.
Definition: muttlib.c:65
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:315
static const char * XdgDefaults[]
XDG default locations.
Definition: muttlib.c:71
+ 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 935 of file muttlib.c.

936{
937 enum MailboxType mb_type = mx_path_probe(path);
938
939 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
940 if (mb_type == MUTT_IMAP)
941 {
942 imap_get_parent_path(path, buf, buflen);
943 }
944 else if (mb_type == MUTT_NOTMUCH)
945 {
946 mutt_str_copy(buf, c_folder, buflen);
947 }
948 else
949 {
950 mutt_str_copy(buf, path, buflen);
951 int n = mutt_str_len(buf);
952 if (n == 0)
953 return;
954
955 /* remove any final trailing '/' */
956 if (buf[n - 1] == '/')
957 buf[n - 1] = '\0';
958
959 /* Remove everything until the next slash */
960 for (n--; ((n >= 0) && (buf[n] != '/')); n--)
961 ; // do nothing
962
963 if (n > 0)
964 {
965 buf[n] = '\0';
966 }
967 else
968 {
969 buf[0] = '/';
970 buf[1] = '\0';
971 }
972 }
973}
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
Definition: util.c:164
+ 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 981 of file muttlib.c.

982{
983 if (!buf || !path)
984 return;
985
986 buf_reset(buf);
987
988 for (; *path; path++)
989 {
990 if ((slash && (*path == '/')) || !strchr(FilenameSafeChars, *path))
991 buf_addch(buf, '_');
992 else
993 buf_addch(buf, *path);
994 }
995}
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()

void mutt_str_pretty_size ( char *  buf,
size_t  buflen,
size_t  num 
)

Display an abbreviated size, like 3.4K.

Parameters
bufBuffer for the result
buflenLength of the buffer
numNumber to abbreviate

Definition at line 1003 of file muttlib.c.

1004{
1005 if (!buf || (buflen == 0))
1006 return;
1007
1008 const bool c_size_show_bytes = cs_subset_bool(NeoMutt->sub, "size_show_bytes");
1009 const bool c_size_show_fractions = cs_subset_bool(NeoMutt->sub, "size_show_fractions");
1010 const bool c_size_show_mb = cs_subset_bool(NeoMutt->sub, "size_show_mb");
1011 const bool c_size_units_on_left = cs_subset_bool(NeoMutt->sub, "size_units_on_left");
1012
1013 if (c_size_show_bytes && (num < 1024))
1014 {
1015 snprintf(buf, buflen, "%d", (int) num);
1016 }
1017 else if (num == 0)
1018 {
1019 mutt_str_copy(buf, c_size_units_on_left ? "K0" : "0K", buflen);
1020 }
1021 else if (c_size_show_fractions && (num < 10189)) /* 0.1K - 9.9K */
1022 {
1023 snprintf(buf, buflen, c_size_units_on_left ? "K%3.1f" : "%3.1fK",
1024 (num < 103) ? 0.1 : (num / 1024.0));
1025 }
1026 else if (!c_size_show_mb || (num < 1023949)) /* 10K - 999K */
1027 {
1028 /* 51 is magic which causes 10189/10240 to be rounded up to 10 */
1029 snprintf(buf, buflen, c_size_units_on_left ? ("K%zu") : ("%zuK"), (num + 51) / 1024);
1030 }
1031 else if (c_size_show_fractions && (num < 10433332)) /* 1.0M - 9.9M */
1032 {
1033 snprintf(buf, buflen, c_size_units_on_left ? "M%3.1f" : "%3.1fM", num / 1048576.0);
1034 }
1035 else /* 10M+ */
1036 {
1037 /* (10433332 + 52428) / 1048576 = 10 */
1038 snprintf(buf, buflen, c_size_units_on_left ? ("M%zu") : ("%zuM"), (num + 52428) / 1048576);
1039 }
1040}
+ 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 1049 of file muttlib.c.

1050{
1051 /* don't add a NULL or empty string to the list */
1052 if (!str || (*str == '\0'))
1053 return;
1054
1055 /* check to make sure the item is not already on this list */
1056 struct ListNode *np = NULL;
1057 STAILQ_FOREACH(np, head, entries)
1058 {
1059 if (mutt_istr_equal(str, np->data))
1060 {
1061 return;
1062 }
1063 }
1065}
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 1074 of file muttlib.c.

1075{
1076 if (mutt_str_equal("*", str))
1077 {
1078 mutt_list_free(head); /* "unCMD *" means delete all current entries */
1079 }
1080 else
1081 {
1082 struct ListNode *np = NULL, *tmp = NULL;
1083 STAILQ_FOREACH_SAFE(np, head, entries, tmp)
1084 {
1085 if (mutt_istr_equal(str, np->data))
1086 {
1087 STAILQ_REMOVE(head, np, ListNode, entries);
1088 FREE(&np->data);
1089 FREE(&np);
1090 break;
1091 }
1092 }
1093 }
1094}
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:660
#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:

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:44
@ XDG_CONFIG_DIRS
XDG system dir: /etc/xdg.
Definition: protos.h:45

Accepted XDG environment variables.

Definition at line 65 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 71 of file muttlib.c.