NeoMutt  2024-02-01-23-g345d7b
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 "imap/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 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 *b)
 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
  • 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 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:178
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:412
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:97
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:705
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:36
char * data
Pointer to data.
Definition: buffer.h:37
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:345
+ 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
237 mutt_default_save(p, e);
238
239 email_free(&e);
240 /* Avoid infinite recursion if the resulting folder starts with '@' */
241 if (*p->data != '@')
242 recurse = true;
243
244 tail = "";
245 }
246 break;
247 }
248
249 case '>':
250 {
251 const char *const c_mbox = cs_subset_string(NeoMutt->sub, "mbox");
252 buf_strcpy(p, c_mbox);
253 tail = s + 1;
254 break;
255 }
256
257 case '<':
258 {
259 const char *const c_record = cs_subset_string(NeoMutt->sub, "record");
260 buf_strcpy(p, c_record);
261 tail = s + 1;
262 break;
263 }
264
265 case '!':
266 {
267 if (s[1] == '!')
268 {
270 tail = s + 2;
271 }
272 else
273 {
274 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
275 buf_strcpy(p, c_spool_file);
276 tail = s + 1;
277 }
278 break;
279 }
280
281 case '-':
282 {
284 tail = s + 1;
285 break;
286 }
287
288 case '^':
289 {
291 tail = s + 1;
292 break;
293 }
294
295 default:
296 {
297 buf_reset(p);
298 tail = s;
299 }
300 }
301
302 if (regex && *(buf_string(p)) && !recurse)
303 {
305 buf_printf(tmp, "%s%s", buf_string(q), tail);
306 }
307 else
308 {
309 buf_printf(tmp, "%s%s", buf_string(p), tail);
310 }
311
312 buf_copy(buf, tmp);
313 } while (recurse);
314
317 buf_pool_release(&tmp);
318
319 /* Rewrite IMAP path in canonical form - aids in string comparisons of
320 * folders. May possibly fail, in which case buf should be the same. */
321 if (imap_path_probe(buf_string(buf), NULL) == MUTT_IMAP)
322 imap_expand_path(buf);
323}
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:282
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:93
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:618
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:354
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:38
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:80
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:747
char * LastFolder
Previously selected mailbox.
Definition: globals.c:44
char * CurrentFolder
Currently selected mailbox.
Definition: globals.c:43
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2342
void mutt_default_save(struct Buffer *path, struct Email *e)
Find the default save path for an email.
Definition: hook.c:748
int imap_expand_path(struct Buffer *path)
Buffer wrapper around imap_path_canon()
Definition: imap.c:2382
#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:1319
#define TAILQ_EMPTY(head)
Definition: queue.h:721
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 331 of file muttlib.c.

332{
333 buf_expand_path_regex(buf, false);
334}
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 345 of file muttlib.c.

346{
347 struct Buffer *tmp = buf_pool_get();
348
349 buf_addstr(tmp, NONULL(buf));
350 buf_expand_path_regex(tmp, regex);
351 mutt_str_copy(buf, buf_string(tmp), buflen);
352
353 buf_pool_release(&tmp);
354
355 return buf;
356}
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:243
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:630
+ 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 370 of file muttlib.c.

371{
372 regmatch_t pat_match[1] = { 0 };
373 char *p = NULL;
374
375 if (!pw || !pw->pw_gecos)
376 return NULL;
377
378 memset(dest, 0, destlen);
379
380 const struct Regex *c_gecos_mask = cs_subset_regex(NeoMutt->sub, "gecos_mask");
381 if (mutt_regex_capture(c_gecos_mask, pw->pw_gecos, 1, pat_match))
382 {
383 mutt_str_copy(dest, pw->pw_gecos + pat_match[0].rm_so,
384 MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
385 }
386 else if ((p = strchr(pw->pw_gecos, ',')))
387 {
388 mutt_str_copy(dest, pw->pw_gecos, MIN(destlen, p - pw->pw_gecos + 1));
389 }
390 else
391 {
392 mutt_str_copy(dest, pw->pw_gecos, destlen);
393 }
394
395 size_t pwnl = strlen(pw->pw_name);
396
397 for (int idx = 0; dest[idx]; idx++)
398 {
399 if (dest[idx] == '&')
400 {
401 memmove(&dest[idx + pwnl], &dest[idx + 1],
402 MAX((ssize_t) (destlen - idx - pwnl - 1), 0));
403 memcpy(&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl));
404 dest[idx] = toupper((unsigned char) dest[idx]);
405 }
406 }
407
408 return dest;
409}
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:622
Cached regular expression.
Definition: regex3.h:85
+ 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 417 of file muttlib.c.

418{
419 switch (b->type)
420 {
421 case TYPE_TEXT:
422 if (mutt_istr_equal("plain", b->subtype))
423 return false;
424 break;
425 case TYPE_APPLICATION:
427 return false;
429 return false;
430 break;
431
432 case TYPE_MULTIPART:
433 case TYPE_MESSAGE:
434 return false;
435 }
436
437 return true;
438}
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:534
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:595
@ 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:721
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:90
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:91
#define WithCrypto
Definition: lib.h:116
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 445 of file muttlib.c.

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

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

558{
559 if (!buf || !buf->data)
560 return;
561 /* This reduces the size of the Buffer, so we can pass it through.
562 * We adjust the size just to make sure buf->data is not NULL though */
563 buf_alloc(buf, PATH_MAX);
564 mutt_pretty_mailbox(buf->data, buf->dsize);
565 buf_fix_dptr(buf);
566}
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:199
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:478
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 579 of file muttlib.c.

581{
582 struct stat st = { 0 };
583
584 buf_strcpy(fname, path);
585 if (access(buf_string(fname), F_OK) != 0)
586 return 0;
587 if (stat(buf_string(fname), &st) != 0)
588 return -1;
589 if (S_ISDIR(st.st_mode))
590 {
591 enum QuadOption ans = MUTT_NO;
592 if (directory)
593 {
594 switch (mw_multi_choice
595 /* L10N: Means "The path you specified as the destination file is a directory."
596 See the msgid "Save to file: " (alias.c, recvattach.c)
597 These three letters correspond to the choices in the string. */
598 (_("File is a directory, save under it: (y)es, (n)o, (a)ll?"), _("yna")))
599 {
600 case 3: /* all */
601 mutt_str_replace(directory, buf_string(fname));
602 break;
603 case 1: /* yes */
604 FREE(directory);
605 break;
606 case -1: /* abort */
607 FREE(directory);
608 return -1;
609 case 2: /* no */
610 FREE(directory);
611 return 1;
612 }
613 }
614 /* L10N: Means "The path you specified as the destination file is a directory."
615 See the msgid "Save to file: " (alias.c, recvattach.c) */
616 else if ((ans = query_yesorno(_("File is a directory, save under it?"), MUTT_YES)) != MUTT_YES)
617 return (ans == MUTT_NO) ? 1 : -1;
618
619 struct Buffer *tmp = buf_pool_get();
620 buf_strcpy(tmp, mutt_path_basename(NONULL(attname)));
621 struct FileCompletionData cdata = { false, NULL, NULL, NULL };
622 if ((mw_get_field(_("File under directory: "), tmp, MUTT_COMP_CLEAR,
623 HC_FILE, &CompleteFileOps, &cdata) != 0) ||
624 buf_is_empty(tmp))
625 {
626 buf_pool_release(&tmp);
627 return (-1);
628 }
629 buf_concat_path(fname, path, buf_string(tmp));
630 buf_pool_release(&tmp);
631 }
632
633 if ((*opt == MUTT_SAVE_NO_FLAGS) && (access(buf_string(fname), F_OK) == 0))
634 {
635 char buf[4096] = { 0 };
636 snprintf(buf, sizeof(buf), "%s - %s", buf_string(fname),
637 // L10N: Options for: File %s exists, (o)verwrite, (a)ppend, or (c)ancel?
638 _("File exists, (o)verwrite, (a)ppend, or (c)ancel?"));
639 switch (mw_multi_choice(buf, _("oac")))
640 {
641 case -1: /* abort */
642 return -1;
643 case 3: /* cancel */
644 return 1;
645
646 case 2: /* append */
647 *opt = MUTT_SAVE_APPEND;
648 break;
649 case 1: /* overwrite */
650 *opt = MUTT_SAVE_OVERWRITE;
651 break;
652 }
653 }
654 return 0;
655}
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:308
size_t buf_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:526
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:274
int mw_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question -.
Definition: question.c:64
@ HC_FILE
Files.
Definition: lib.h:54
#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:281
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:329
#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_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:334
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 666 of file muttlib.c.

667{
668 if (addr && addr->mailbox)
669 {
670 mutt_str_copy(buf, buf_string(addr->mailbox), buflen);
671 const bool c_save_address = cs_subset_bool(NeoMutt->sub, "save_address");
672 if (!c_save_address)
673 {
674 char *p = strpbrk(buf, "%@");
675 if (p)
676 *p = '\0';
677 }
678 mutt_str_lower(buf);
679 }
680 else
681 {
682 *buf = '\0';
683 }
684}
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:362
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 691 of file muttlib.c.

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

722{
723 buf_save_path(dest, a);
724 for (char *p = dest->data; *p; p++)
725 if ((*p == '/') || isspace(*p) || !IsPrint((unsigned char) *p))
726 *p = '_';
727}
#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:691
+ 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 1279 of file muttlib.c.

1280{
1281 FILE *fp = NULL;
1282 struct stat st = { 0 };
1283
1284 size_t len = mutt_str_len(path);
1285 if (len == 0)
1286 {
1287 return NULL;
1288 }
1289
1290 if (path[len - 1] == '|')
1291 {
1292 /* read from a pipe */
1293
1294 char *p = mutt_str_dup(path);
1295
1296 p[len - 1] = 0;
1297 mutt_endwin();
1298 *thepid = filter_create(p, NULL, &fp, NULL, EnvList);
1299 FREE(&p);
1300 }
1301 else
1302 {
1303 if (stat(path, &st) < 0)
1304 return NULL;
1305 if (S_ISDIR(st.st_mode))
1306 {
1307 errno = EINVAL;
1308 return NULL;
1309 }
1310 fp = mutt_file_fopen(path, "r");
1311 *thepid = -1;
1312 }
1313 return fp;
1314}
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:153
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:147
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:208
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:78
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 1324 of file muttlib.c.

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

1422{
1423 const short c_sleep_time = cs_subset_number(NeoMutt->sub, "sleep_time");
1424 if (c_sleep_time > s)
1425 sleep(c_sleep_time);
1426 else if (s)
1427 sleep(s);
1428}
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 1436 of file muttlib.c.

1437{
1438 static char vstring[256];
1439 snprintf(vstring, sizeof(vstring), "NeoMutt %s%s", PACKAGE_VERSION, GitVer);
1440 return vstring;
1441}
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 1450 of file muttlib.c.

1451{
1452 char *p = mutt_str_dup(src);
1453 int rc = mutt_ch_convert_string(&p, cc_charset(), "us-ascii", MUTT_ICONV_NO_FLAGS);
1454 size_t len = buf_strcpy(buf, (rc == 0) ? NONULL(p) : NONULL(src));
1455
1456 /* convert the path to POSIX "Portable Filename Character Set" */
1457 for (size_t i = 0; i < len; i++)
1458 {
1459 if (!isalnum(buf->data[i]) && !strchr("/.-_", buf->data[i]))
1460 {
1461 buf->data[i] = '_';
1462 }
1463 }
1464 FREE(&p);
1465}
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:830
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:72
+ 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 1475 of file muttlib.c.

1476{
1477 const char *xdg_env = mutt_str_getenv(XdgEnvVars[type]);
1478 char *xdg = xdg_env ? mutt_str_dup(xdg_env) : mutt_str_dup(XdgDefaults[type]);
1479 char *x = xdg; /* mutt_str_sep() changes xdg, so free x instead later */
1480 char *token = NULL;
1481 int rc = 0;
1482
1483 while ((token = mutt_str_sep(&xdg, ":")))
1484 {
1485 if (buf_printf(buf, "%s/%s/neomuttrc", token, PACKAGE) < 0)
1486 continue;
1487 buf_expand_path(buf);
1488 if (access(buf_string(buf), F_OK) == 0)
1489 {
1490 rc = 1;
1491 break;
1492 }
1493
1494 if (buf_printf(buf, "%s/%s/Muttrc", token, PACKAGE) < 0)
1495 continue;
1496 buf_expand_path(buf);
1497 if (access(buf_string(buf), F_OK) == 0)
1498 {
1499 rc = 1;
1500 break;
1501 }
1502 }
1503
1504 FREE(&x);
1505 return rc;
1506}
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:775
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:68
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:331
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 1514 of file muttlib.c.

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

1623{
1624 if (!buf || !path)
1625 return;
1626
1627 buf_reset(buf);
1628
1629 for (; *path; path++)
1630 {
1631 if ((slash && (*path == '/')) || !strchr(FilenameSafeChars, *path))
1632 buf_addch(buf, '_');
1633 else
1634 buf_addch(buf, *path);
1635 }
1636}
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:258
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 1644 of file muttlib.c.

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

1691{
1692 /* don't add a NULL or empty string to the list */
1693 if (!str || (*str == '\0'))
1694 return;
1695
1696 /* check to make sure the item is not already on this list */
1697 struct ListNode *np = NULL;
1698 STAILQ_FOREACH(np, head, entries)
1699 {
1700 if (mutt_istr_equal(str, np->data))
1701 {
1702 return;
1703 }
1704 }
1706}
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 1715 of file muttlib.c.

1716{
1717 if (mutt_str_equal("*", str))
1718 {
1719 mutt_list_free(head); /* "unCMD *" means delete all current entries */
1720 }
1721 else
1722 {
1723 struct ListNode *np = NULL, *tmp = NULL;
1724 STAILQ_FOREACH_SAFE(np, head, entries, tmp)
1725 {
1726 if (mutt_istr_equal(str, np->data))
1727 {
1728 STAILQ_REMOVE(head, np, ListNode, entries);
1729 FREE(&np->data);
1730 FREE(&np);
1731 break;
1732 }
1733 }
1734 }
1735}
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:709
#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:44
@ XDG_CONFIG_DIRS
XDG system dir: /etc/xdg.
Definition: protos.h:45

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.