NeoMutt
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 <stdint.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 "ncrypt/lib.h"
#include "parse/lib.h"
#include "question/lib.h"
#include "format_flags.h"
#include "globals.h"
#include "hook.h"
#include "mx.h"
#include "protos.h"
#include "imap/lib.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.
 
char * mutt_expand_path (char *buf, size_t buflen)
 Create the canonical path.
 
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_expand_path_regex (char *buf, size_t buflen, bool regex)
 Create the canonical path (with regex char escaping)
 
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 *m)
 Does this type need a mailcap entry do display.
 
bool mutt_is_text_part (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.
 
void mutt_expando_format (char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
 Expand expandos (x) in a string -.
 
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)
 
int mutt_inbox_cmp (const char *a, const char *b)
 Do two folders share the same path and one is an inbox -.
 
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
  • 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 87 of file muttlib.c.

88{
89 if (!(buf->data && (buf->data[0] != '\0')))
90 {
91 buf_mktemp(buf);
92 }
93 else
94 {
95 struct Buffer *prefix = buf_pool_get();
96 buf_strcpy(prefix, buf->data);
97 mutt_file_sanitize_filename(prefix->data, true);
98 const char *const c_tmp_dir = cs_subset_path(NeoMutt->sub, "tmp_dir");
99 buf_printf(buf, "%s/%s", NONULL(c_tmp_dir), buf_string(prefix));
100
101 struct stat st = { 0 };
102 if ((lstat(buf_string(buf), &st) == -1) && (errno == ENOENT))
103 goto out;
104
105 char *suffix = strchr(prefix->data, '.');
106 if (suffix)
107 {
108 *suffix = '\0';
109 suffix++;
110 }
111 buf_mktemp_pfx_sfx(buf, prefix->data, suffix);
112
113 out:
114 buf_pool_release(&prefix);
115 }
116}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:173
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:407
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:169
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:667
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:34
char * data
Pointer to data.
Definition: buffer.h:35
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
#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:

◆ mutt_expand_path()

char * mutt_expand_path ( char *  buf,
size_t  buflen 
)

Create the canonical path.

Parameters
bufBuffer with path
buflenLength of buffer
Return values
ptrThe expanded string
Note
The path is expanded in-place

Definition at line 126 of file muttlib.c.

127{
128 return mutt_expand_path_regex(buf, buflen, false);
129}
char * mutt_expand_path_regex(char *buf, size_t buflen, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:349
+ 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 138 of file muttlib.c.

139{
140 const char *s = NULL;
141 const char *tail = "";
142
143 bool recurse = false;
144
145 struct Buffer *p = buf_pool_get();
146 struct Buffer *q = buf_pool_get();
147 struct Buffer *tmp = buf_pool_get();
148
149 do
150 {
151 recurse = false;
152 s = buf_string(buf);
153
154 switch (*s)
155 {
156 case '~':
157 {
158 if ((s[1] == '/') || (s[1] == '\0'))
159 {
161 tail = s + 1;
162 }
163 else
164 {
165 char *t = strchr(s + 1, '/');
166 if (t)
167 *t = '\0';
168
169 struct passwd *pw = getpwnam(s + 1);
170 if (pw)
171 {
172 buf_strcpy(p, pw->pw_dir);
173 if (t)
174 {
175 *t = '/';
176 tail = t;
177 }
178 else
179 {
180 tail = "";
181 }
182 }
183 else
184 {
185 /* user not found! */
186 if (t)
187 *t = '/';
188 buf_reset(p);
189 tail = s;
190 }
191 }
192 break;
193 }
194
195 case '=':
196 case '+':
197 {
198 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
199 enum MailboxType mb_type = mx_path_probe(c_folder);
200
201 /* if folder = {host} or imap[s]://host/: don't append slash */
202 if ((mb_type == MUTT_IMAP) && ((c_folder[strlen(c_folder) - 1] == '}') ||
203 (c_folder[strlen(c_folder) - 1] == '/')))
204 {
205 buf_strcpy(p, NONULL(c_folder));
206 }
207 else if (mb_type == MUTT_NOTMUCH)
208 {
209 buf_strcpy(p, NONULL(c_folder));
210 }
211 else if (c_folder && (c_folder[strlen(c_folder) - 1] == '/'))
212 {
213 buf_strcpy(p, NONULL(c_folder));
214 }
215 else
216 {
217 buf_printf(p, "%s/", NONULL(c_folder));
218 }
219
220 tail = s + 1;
221 break;
222 }
223
224 /* elm compatibility, @ expands alias to user name */
225
226 case '@':
227 {
228 struct AddressList *al = alias_lookup(s + 1);
229 if (al && !TAILQ_EMPTY(al))
230 {
231 struct Email *e = email_new();
232 e->env = mutt_env_new();
233 mutt_addrlist_copy(&e->env->from, al, false);
234 mutt_addrlist_copy(&e->env->to, al, false);
235
236 /* TODO: fix mutt_default_save() to use Buffer */
238 mutt_default_save(p->data, p->dsize, e);
239 buf_fix_dptr(p);
240
241 email_free(&e);
242 /* Avoid infinite recursion if the resulting folder starts with '@' */
243 if (*p->data != '@')
244 recurse = true;
245
246 tail = "";
247 }
248 break;
249 }
250
251 case '>':
252 {
253 const char *const c_mbox = cs_subset_string(NeoMutt->sub, "mbox");
254 buf_strcpy(p, c_mbox);
255 tail = s + 1;
256 break;
257 }
258
259 case '<':
260 {
261 const char *const c_record = cs_subset_string(NeoMutt->sub, "record");
262 buf_strcpy(p, c_record);
263 tail = s + 1;
264 break;
265 }
266
267 case '!':
268 {
269 if (s[1] == '!')
270 {
272 tail = s + 2;
273 }
274 else
275 {
276 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
277 buf_strcpy(p, c_spool_file);
278 tail = s + 1;
279 }
280 break;
281 }
282
283 case '-':
284 {
286 tail = s + 1;
287 break;
288 }
289
290 case '^':
291 {
293 tail = s + 1;
294 break;
295 }
296
297 default:
298 {
299 buf_reset(p);
300 tail = s;
301 }
302 }
303
304 if (regex && *(buf_string(p)) && !recurse)
305 {
307 buf_printf(tmp, "%s%s", buf_string(q), tail);
308 }
309 else
310 {
311 buf_printf(tmp, "%s%s", buf_string(p), tail);
312 }
313
314 buf_copy(buf, tmp);
315 } while (recurse);
316
319 buf_pool_release(&tmp);
320
321#ifdef USE_IMAP
322 /* Rewrite IMAP path in canonical form - aids in string comparisons of
323 * folders. May possibly fail, in which case buf should be the same. */
324 if (imap_path_probe(buf_string(buf), NULL) == MUTT_IMAP)
325 imap_expand_path(buf);
326#endif
327}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:762
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:280
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:194
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:572
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:349
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
char * HomeDir
User's home directory.
Definition: globals.c:39
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:43
int mutt_file_sanitize_regex(struct Buffer *dest, const char *src)
Escape any regex-magic characters in a string.
Definition: file.c:709
char * LastFolder
Previously selected mailbox.
Definition: globals.c:45
char * CurrentFolder
Currently selected mailbox.
Definition: globals.c:44
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2329
void mutt_default_save(char *path, size_t pathlen, struct Email *e)
Find the default save path for an email.
Definition: hook.c:736
int imap_expand_path(struct Buffer *path)
Buffer wrapper around imap_path_canon()
Definition: imap.c:2369
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
#define PATH_MAX
Definition: mutt.h:41
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1343
#define TAILQ_EMPTY(head)
Definition: queue.h:721
size_t dsize
Length of data.
Definition: buffer.h:37
The envelope/body of an email.
Definition: email.h:37
struct Envelope * env
Envelope information.
Definition: email.h:66
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 335 of file muttlib.c.

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

◆ mutt_expand_path_regex()

char * mutt_expand_path_regex ( char *  buf,
size_t  buflen,
bool  regex 
)

Create the canonical path (with regex char escaping)

Parameters
bufBuffer with path
buflenLength of buffer
regexIf true, escape any regex characters
Return values
ptrThe expanded string
Note
The path is expanded in-place

Definition at line 349 of file muttlib.c.

350{
351 struct Buffer *tmp = buf_pool_get();
352
353 buf_addstr(tmp, NONULL(buf));
354 buf_expand_path_regex(tmp, regex);
355 mutt_str_copy(buf, buf_string(tmp), buflen);
356
357 buf_pool_release(&tmp);
358
359 return buf;
360}
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:238
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:653
+ 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 374 of file muttlib.c.

375{
376 regmatch_t pat_match[1];
377 size_t pwnl;
378 char *p = NULL;
379
380 if (!pw || !pw->pw_gecos)
381 return NULL;
382
383 memset(dest, 0, destlen);
384
385 const struct Regex *c_gecos_mask = cs_subset_regex(NeoMutt->sub, "gecos_mask");
386 if (mutt_regex_capture(c_gecos_mask, pw->pw_gecos, 1, pat_match))
387 {
388 mutt_str_copy(dest, pw->pw_gecos + pat_match[0].rm_so,
389 MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
390 }
391 else if ((p = strchr(pw->pw_gecos, ',')))
392 {
393 mutt_str_copy(dest, pw->pw_gecos, MIN(destlen, p - pw->pw_gecos + 1));
394 }
395 else
396 {
397 mutt_str_copy(dest, pw->pw_gecos, destlen);
398 }
399
400 pwnl = strlen(pw->pw_name);
401
402 for (int idx = 0; dest[idx]; idx++)
403 {
404 if (dest[idx] == '&')
405 {
406 memmove(&dest[idx + pwnl], &dest[idx + 1],
407 MAX((ssize_t) (destlen - idx - pwnl - 1), 0));
408 memcpy(&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl));
409 dest[idx] = toupper((unsigned char) dest[idx]);
410 }
411 }
412
413 return dest;
414}
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:218
#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:619
Cached regular expression.
Definition: regex3.h:89
+ 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 m)

Does this type need a mailcap entry do display.

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

Definition at line 422 of file muttlib.c.

423{
424 switch (m->type)
425 {
426 case TYPE_TEXT:
427 if (mutt_istr_equal("plain", m->subtype))
428 return false;
429 break;
430 case TYPE_APPLICATION:
432 return false;
434 return false;
435 break;
436
437 case TYPE_MULTIPART:
438 case TYPE_MESSAGE:
439 return false;
440 }
441
442 return true;
443}
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:537
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:598
@ 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:810
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:91
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:92
#define WithCrypto
Definition: lib.h:117
char * subtype
content-type subtype
Definition: body.h:60
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 ( 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 450 of file muttlib.c.

451{
452 int t = b->type;
453 char *s = b->subtype;
454
456 return false;
457
458 if (t == TYPE_TEXT)
459 return true;
460
461 if (t == TYPE_MESSAGE)
462 {
463 if (mutt_istr_equal("delivery-status", s))
464 return true;
465 }
466
467 if (((WithCrypto & APPLICATION_PGP) != 0) && (t == TYPE_APPLICATION))
468 {
469 if (mutt_istr_equal("pgp-keys", s))
470 return true;
471 }
472
473 return false;
474}
+ 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 483 of file muttlib.c.

484{
485 if (!buf)
486 return;
487
488 char *p = buf, *q = buf;
489 size_t len;
490 enum UrlScheme scheme;
491 char tmp[PATH_MAX] = { 0 };
492
493 scheme = url_check_scheme(buf);
494
495 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
496 if ((scheme == U_IMAP) || (scheme == U_IMAPS))
497 {
498 imap_pretty_mailbox(buf, buflen, c_folder);
499 return;
500 }
501
502 if (scheme == U_NOTMUCH)
503 return;
504
505 /* if buf is an url, only collapse path component */
506 if (scheme != U_UNKNOWN)
507 {
508 p = strchr(buf, ':') + 1;
509 if (mutt_strn_equal(p, "//", 2))
510 q = strchr(p + 2, '/');
511 if (!q)
512 q = strchr(p, '\0');
513 p = q;
514 }
515
516 /* cleanup path */
517 if (strstr(p, "//") || strstr(p, "/./"))
518 {
519 /* first attempt to collapse the pathname, this is more
520 * lightweight than realpath() and doesn't resolve links */
521 while (*p)
522 {
523 if ((p[0] == '/') && (p[1] == '/'))
524 {
525 *q++ = '/';
526 p += 2;
527 }
528 else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
529 {
530 *q++ = '/';
531 p += 3;
532 }
533 else
534 {
535 *q++ = *p++;
536 }
537 }
538 *q = '\0';
539 }
540 else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
541 realpath(p, tmp))
542 {
543 mutt_str_copy(p, tmp, buflen - (p - buf));
544 }
545
546 if ((len = mutt_str_startswith(buf, c_folder)) && (buf[len] == '/'))
547 {
548 *buf++ = '=';
549 memmove(buf, buf + len, mutt_str_len(buf + len) + 1);
550 }
551 else if ((len = mutt_str_startswith(buf, HomeDir)) && (buf[len] == '/'))
552 {
553 *buf++ = '~';
554 memmove(buf, buf + len - 1, mutt_str_len(buf + len - 1) + 1);
555 }
556}
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:578
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:497
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:228
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:568
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 562 of file muttlib.c.

563{
564 if (!buf || !buf->data)
565 return;
566 /* This reduces the size of the Buffer, so we can pass it through.
567 * We adjust the size just to make sure buf->data is not NULL though */
568 buf_alloc(buf, PATH_MAX);
569 mutt_pretty_mailbox(buf->data, buf->dsize);
570 buf_fix_dptr(buf);
571}
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:483
+ 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 584 of file muttlib.c.

586{
587 struct stat st = { 0 };
588
589 buf_strcpy(fname, path);
590 if (access(buf_string(fname), F_OK) != 0)
591 return 0;
592 if (stat(buf_string(fname), &st) != 0)
593 return -1;
594 if (S_ISDIR(st.st_mode))
595 {
596 enum QuadOption ans = MUTT_NO;
597 if (directory)
598 {
599 switch (mw_multi_choice
600 /* L10N: Means "The path you specified as the destination file is a directory."
601 See the msgid "Save to file: " (alias.c, recvattach.c)
602 These three letters correspond to the choices in the string. */
603 (_("File is a directory, save under it: (y)es, (n)o, (a)ll?"), _("yna")))
604 {
605 case 3: /* all */
606 mutt_str_replace(directory, buf_string(fname));
607 break;
608 case 1: /* yes */
609 FREE(directory);
610 break;
611 case -1: /* abort */
612 FREE(directory);
613 return -1;
614 case 2: /* no */
615 FREE(directory);
616 return 1;
617 }
618 }
619 /* L10N: Means "The path you specified as the destination file is a directory."
620 See the msgid "Save to file: " (alias.c, recvattach.c) */
621 else if ((ans = query_yesorno(_("File is a directory, save under it?"), MUTT_YES)) != MUTT_YES)
622 return (ans == MUTT_NO) ? 1 : -1;
623
624 struct Buffer *tmp = buf_pool_get();
625 buf_strcpy(tmp, mutt_path_basename(NONULL(attname)));
626 struct FileCompletionData cdata = { false, NULL, NULL, NULL };
627 if ((mw_get_field(_("File under directory: "), tmp, MUTT_COMP_CLEAR,
628 HC_FILE, &CompleteMailboxOps, &cdata) != 0) ||
629 buf_is_empty(tmp))
630 {
631 buf_pool_release(&tmp);
632 return (-1);
633 }
634 buf_concat_path(fname, path, buf_string(tmp));
635 buf_pool_release(&tmp);
636 }
637
638 if ((*opt == MUTT_SAVE_NO_FLAGS) && (access(buf_string(fname), F_OK) == 0))
639 {
640 char buf[4096] = { 0 };
641 snprintf(buf, sizeof(buf), "%s - %s", buf_string(fname),
642 // L10N: Options for: File %s exists, (o)verwrite, (a)ppend, or (c)ancel?
643 _("File exists, (o)verwrite, (a)ppend, or (c)ancel?"));
644 switch (mw_multi_choice(buf, _("oac")))
645 {
646 case -1: /* abort */
647 return -1;
648 case 3: /* cancel */
649 return 1;
650
651 case 2: /* append */
652 *opt = MUTT_SAVE_APPEND;
653 break;
654 case 1: /* overwrite */
655 *opt = MUTT_SAVE_OVERWRITE;
656 break;
657 }
658 }
659 return 0;
660}
const struct CompleteOps CompleteMailboxOps
Auto-Completion of Files / Mailboxes.
Definition: complete.c:160
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
size_t buf_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:484
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:275
int mw_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question -.
Definition: question.c:60
@ HC_FILE
Files.
Definition: lib.h:52
#define FREE(x)
Definition: memory.h:45
#define _(a)
Definition: message.h:28
const char * mutt_path_basename(const char *path)
Find the last component for a pathname.
Definition: path.c:314
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:327
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:56
@ MUTT_SAVE_APPEND
Append to existing file.
Definition: mutt_attach.h:59
@ MUTT_SAVE_OVERWRITE
Overwrite existing file.
Definition: mutt_attach.h:60
@ MUTT_SAVE_NO_FLAGS
No flags set.
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:330
Input for the file completion function.
Definition: curs_lib.h:49
+ 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 671 of file muttlib.c.

672{
673 if (addr && addr->mailbox)
674 {
675 mutt_str_copy(buf, buf_string(addr->mailbox), buflen);
676 const bool c_save_address = cs_subset_bool(NeoMutt->sub, "save_address");
677 if (!c_save_address)
678 {
679 char *p = strpbrk(buf, "%@");
680 if (p)
681 *p = '\0';
682 }
683 mutt_str_lower(buf);
684 }
685 else
686 {
687 *buf = '\0';
688 }
689}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
Definition: string.c:385
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 696 of file muttlib.c.

697{
698 if (a && a->mailbox)
699 {
700 buf_copy(dest, a->mailbox);
701 const bool c_save_address = cs_subset_bool(NeoMutt->sub, "save_address");
702 if (!c_save_address)
703 {
704 char *p = strpbrk(dest->data, "%@");
705 if (p)
706 {
707 *p = '\0';
708 buf_fix_dptr(dest);
709 }
710 }
711 mutt_str_lower(dest->data);
712 }
713 else
714 {
715 buf_reset(dest);
716 }
717}
+ 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 726 of file muttlib.c.

727{
728 buf_save_path(dest, a);
729 for (char *p = dest->data; *p; p++)
730 if ((*p == '/') || isspace(*p) || !IsPrint((unsigned char) *p))
731 *p = '_';
732}
#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:696
+ 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 1282 of file muttlib.c.

1283{
1284 FILE *fp = NULL;
1285 struct stat st = { 0 };
1286
1287 size_t len = mutt_str_len(path);
1288 if (len == 0)
1289 {
1290 return NULL;
1291 }
1292
1293 if (path[len - 1] == '|')
1294 {
1295 /* read from a pipe */
1296
1297 char *p = mutt_str_dup(path);
1298
1299 p[len - 1] = 0;
1300 mutt_endwin();
1301 *thepid = filter_create(p, NULL, &fp, NULL, EnvList);
1302 FREE(&p);
1303 }
1304 else
1305 {
1306 if (stat(path, &st) < 0)
1307 return NULL;
1308 if (S_ISDIR(st.st_mode))
1309 {
1310 errno = EINVAL;
1311 return NULL;
1312 }
1313 fp = fopen(path, "r");
1314 *thepid = -1;
1315 }
1316 return fp;
1317}
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:154
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:207
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:85
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:251
+ 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 1327 of file muttlib.c.

1328{
1329 int rc = 0;
1330
1331 enum MailboxType type = mx_path_probe(s);
1332
1333#ifdef USE_POP
1334 if (type == MUTT_POP)
1335 {
1336 mutt_error(_("Can't save message to POP mailbox"));
1337 return 1;
1338 }
1339#endif
1340
1341 if ((type != MUTT_MAILBOX_ERROR) && (type != MUTT_UNKNOWN) && (mx_access(s, W_OK) == 0))
1342 {
1343 const bool c_confirm_append = cs_subset_bool(NeoMutt->sub, "confirm_append");
1344 if (c_confirm_append)
1345 {
1346 struct Buffer *tmp = buf_pool_get();
1347 buf_printf(tmp, _("Append messages to %s?"), s);
1349 NeoMutt->sub, "confirm_append");
1350 if (ans == MUTT_NO)
1351 rc = 1;
1352 else if (ans == MUTT_ABORT)
1353 rc = -1;
1354 buf_pool_release(&tmp);
1355 }
1356 }
1357
1358#ifdef USE_NNTP
1359 if (type == MUTT_NNTP)
1360 {
1361 mutt_error(_("Can't save message to news server"));
1362 return 0;
1363 }
1364#endif
1365
1366 if (stat(s, st) != -1)
1367 {
1368 if (type == MUTT_MAILBOX_ERROR)
1369 {
1370 mutt_error(_("%s is not a mailbox"), s);
1371 return 1;
1372 }
1373 }
1374 else if (type != MUTT_IMAP)
1375 {
1376 st->st_mtime = 0;
1377 st->st_atime = 0;
1378
1379 /* pathname does not exist */
1380 if (errno == ENOENT)
1381 {
1382 const bool c_confirm_create = cs_subset_bool(NeoMutt->sub, "confirm_create");
1383 if (c_confirm_create)
1384 {
1385 struct Buffer *tmp = buf_pool_get();
1386 buf_printf(tmp, _("Create %s?"), s);
1388 NeoMutt->sub, "confirm_create");
1389 if (ans == MUTT_NO)
1390 rc = 1;
1391 else if (ans == MUTT_ABORT)
1392 rc = -1;
1393 buf_pool_release(&tmp);
1394 }
1395
1396 /* user confirmed with MUTT_YES or set `$confirm_create` */
1397 if (rc == 0)
1398 {
1399 /* create dir recursively */
1400 char *tmp_path = mutt_path_dirname(s);
1401 if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
1402 {
1403 /* report failure & abort */
1404 mutt_perror("%s", s);
1405 FREE(&tmp_path);
1406 return 1;
1407 }
1408 FREE(&tmp_path);
1409 }
1410 }
1411 else
1412 {
1413 mutt_perror("%s", s);
1414 return 1;
1415 }
1416 }
1417
1418 msgwin_clear_text(NULL);
1419 return rc;
1420}
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:977
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_perror(...)
Definition: logging2.h:93
@ 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
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition: msgwin.c:515
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final '/'.
Definition: path.c:381
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
Definition: mx.c:182
@ 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:345
+ 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 1428 of file muttlib.c.

1429{
1430 const short c_sleep_time = cs_subset_number(NeoMutt->sub, "sleep_time");
1431 if (c_sleep_time > s)
1432 sleep(c_sleep_time);
1433 else if (s)
1434 sleep(s);
1435}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:144
+ 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 1443 of file muttlib.c.

1444{
1445 static char vstring[256];
1446 snprintf(vstring, sizeof(vstring), "NeoMutt %s%s", PACKAGE_VERSION, GitVer);
1447 return vstring;
1448}
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 1457 of file muttlib.c.

1458{
1459 char *p = mutt_str_dup(src);
1460 int rc = mutt_ch_convert_string(&p, cc_charset(), "us-ascii", MUTT_ICONV_NO_FLAGS);
1461 size_t len = buf_strcpy(buf, (rc == 0) ? NONULL(p) : NONULL(src));
1462
1463 /* convert the path to POSIX "Portable Filename Character Set" */
1464 for (size_t i = 0; i < len; i++)
1465 {
1466 if (!isalnum(buf->data[i]) && !strchr("/.-_", buf->data[i]))
1467 {
1468 buf->data[i] = '_';
1469 }
1470 }
1471 FREE(&p);
1472}
const char * cc_charset(void)
Get the cached value of $charset.
Definition: config_cache.c:115
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:826
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
+ 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 1482 of file muttlib.c.

1483{
1484 const char *xdg_env = mutt_str_getenv(XdgEnvVars[type]);
1485 char *xdg = xdg_env ? mutt_str_dup(xdg_env) : mutt_str_dup(XdgDefaults[type]);
1486 char *x = xdg; /* mutt_str_sep() changes xdg, so free x instead later */
1487 char *token = NULL;
1488 int rc = 0;
1489
1490 while ((token = mutt_str_sep(&xdg, ":")))
1491 {
1492 if (buf_printf(buf, "%s/%s/neomuttrc", token, PACKAGE) < 0)
1493 continue;
1494 buf_expand_path(buf);
1495 if (access(buf_string(buf), F_OK) == 0)
1496 {
1497 rc = 1;
1498 break;
1499 }
1500
1501 if (buf_printf(buf, "%s/%s/Muttrc", token, PACKAGE) < 0)
1502 continue;
1503 buf_expand_path(buf);
1504 if (access(buf_string(buf), F_OK) == 0)
1505 {
1506 rc = 1;
1507 break;
1508 }
1509 }
1510
1511 FREE(&x);
1512 return rc;
1513}
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:918
char * mutt_str_sep(char **stringp, const char *delim)
Find first occurrence of any of delim characters in *stringp.
Definition: string.c:184
static const char * XdgEnvVars[]
Accepted XDG environment variables.
Definition: muttlib.c:68
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:335
static const char * XdgDefaults[]
XDG default locations.
Definition: muttlib.c:74
+ 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 1521 of file muttlib.c.

1522{
1523 enum MailboxType mb_type = mx_path_probe(path);
1524
1525 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1526 if (mb_type == MUTT_IMAP)
1527 {
1528 imap_get_parent_path(path, buf, buflen);
1529 }
1530 else if (mb_type == MUTT_NOTMUCH)
1531 {
1532 mutt_str_copy(buf, c_folder, buflen);
1533 }
1534 else
1535 {
1536 mutt_str_copy(buf, path, buflen);
1537 int n = mutt_str_len(buf);
1538 if (n == 0)
1539 return;
1540
1541 /* remove any final trailing '/' */
1542 if (buf[n - 1] == '/')
1543 buf[n - 1] = '\0';
1544
1545 /* Remove everything until the next slash */
1546 for (n--; ((n >= 0) && (buf[n] != '/')); n--)
1547 ; // do nothing
1548
1549 if (n > 0)
1550 {
1551 buf[n] = '\0';
1552 }
1553 else
1554 {
1555 buf[0] = '/';
1556 buf[1] = '\0';
1557 }
1558 }
1559}
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
Definition: util.c:160
+ 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 1629 of file muttlib.c.

1630{
1631 if (!buf || !path)
1632 return;
1633
1634 buf_reset(buf);
1635
1636 for (; *path; path++)
1637 {
1638 if ((slash && (*path == '/')) || !strchr(FilenameSafeChars, *path))
1639 buf_addch(buf, '_');
1640 else
1641 buf_addch(buf, *path);
1642 }
1643}
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:253
const char FilenameSafeChars[]
Set of characters <=0x7F that are safe to use in filenames.
Definition: file.c:61
+ 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 1651 of file muttlib.c.

1652{
1653 if (!buf || (buflen == 0))
1654 return;
1655
1656 const bool c_size_show_bytes = cs_subset_bool(NeoMutt->sub, "size_show_bytes");
1657 const bool c_size_show_fractions = cs_subset_bool(NeoMutt->sub, "size_show_fractions");
1658 const bool c_size_show_mb = cs_subset_bool(NeoMutt->sub, "size_show_mb");
1659 const bool c_size_units_on_left = cs_subset_bool(NeoMutt->sub, "size_units_on_left");
1660
1661 if (c_size_show_bytes && (num < 1024))
1662 {
1663 snprintf(buf, buflen, "%d", (int) num);
1664 }
1665 else if (num == 0)
1666 {
1667 mutt_str_copy(buf, c_size_units_on_left ? "K0" : "0K", buflen);
1668 }
1669 else if (c_size_show_fractions && (num < 10189)) /* 0.1K - 9.9K */
1670 {
1671 snprintf(buf, buflen, c_size_units_on_left ? "K%3.1f" : "%3.1fK",
1672 (num < 103) ? 0.1 : (num / 1024.0));
1673 }
1674 else if (!c_size_show_mb || (num < 1023949)) /* 10K - 999K */
1675 {
1676 /* 51 is magic which causes 10189/10240 to be rounded up to 10 */
1677 snprintf(buf, buflen, c_size_units_on_left ? ("K%zu") : ("%zuK"), (num + 51) / 1024);
1678 }
1679 else if (c_size_show_fractions && (num < 10433332)) /* 1.0M - 9.9M */
1680 {
1681 snprintf(buf, buflen, c_size_units_on_left ? "M%3.1f" : "%3.1fM", num / 1048576.0);
1682 }
1683 else /* 10M+ */
1684 {
1685 /* (10433332 + 52428) / 1048576 = 10 */
1686 snprintf(buf, buflen, c_size_units_on_left ? ("M%zu") : ("%zuM"), (num + 52428) / 1048576);
1687 }
1688}
+ 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 1697 of file muttlib.c.

1698{
1699 /* don't add a NULL or empty string to the list */
1700 if (!str || (*str == '\0'))
1701 return;
1702
1703 /* check to make sure the item is not already on this list */
1704 struct ListNode *np = NULL;
1705 STAILQ_FOREACH(np, head, entries)
1706 {
1707 if (mutt_istr_equal(str, np->data))
1708 {
1709 return;
1710 }
1711 }
1713}
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
+ 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 1722 of file muttlib.c.

1723{
1724 if (mutt_str_equal("*", str))
1725 {
1726 mutt_list_free(head); /* "unCMD *" means delete all current entries */
1727 }
1728 else
1729 {
1730 struct ListNode *np = NULL, *tmp = NULL;
1731 STAILQ_FOREACH_SAFE(np, head, entries, tmp)
1732 {
1733 if (mutt_istr_equal(str, np->data))
1734 {
1735 STAILQ_REMOVE(head, np, ListNode, entries);
1736 FREE(&np->data);
1737 FREE(&np);
1738 break;
1739 }
1740 }
1741 }
1742}
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:402
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
+ 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:43
@ XDG_CONFIG_DIRS
XDG system dir: /etc/xdg.
Definition: protos.h:44

Accepted XDG environment variables.

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