NeoMutt  2022-04-29-215-gc12b98
Teaching an old dog new tricks
DOXYGEN
muttlib.c File Reference

Some miscellaneous functions. More...

#include "config.h"
#include <ctype.h>
#include <errno.h>
#include <inttypes.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 "enter/lib.h"
#include "ncrypt/lib.h"
#include "question/lib.h"
#include "format_flags.h"
#include "hook.h"
#include "init.h"
#include "mutt_globals.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. More...
 
char * mutt_expand_path (char *buf, size_t buflen)
 Create the canonical path. More...
 
void mutt_buffer_expand_path_regex (struct Buffer *buf, bool regex)
 Create the canonical path (with regex char escaping) More...
 
void mutt_buffer_expand_path (struct Buffer *buf)
 Create the canonical path. More...
 
char * mutt_expand_path_regex (char *buf, size_t buflen, bool regex)
 Create the canonical path (with regex char escaping) More...
 
char * mutt_gecos_name (char *dest, size_t destlen, struct passwd *pw)
 Lookup a user's real name in /etc/passwd. More...
 
bool mutt_needs_mailcap (struct Body *m)
 Does this type need a mailcap entry do display. More...
 
bool mutt_is_text_part (struct Body *b)
 Is this part of an email in plain text? More...
 
void mutt_buffer_mktemp_full (struct Buffer *buf, const char *prefix, const char *suffix, const char *src, int line)
 Create a temporary file. More...
 
void mutt_mktemp_full (char *buf, size_t buflen, const char *prefix, const char *suffix, const char *src, int line)
 Create a temporary filename. More...
 
void mutt_pretty_mailbox (char *buf, size_t buflen)
 Shorten a mailbox path using '~' or '='. More...
 
void mutt_buffer_pretty_mailbox (struct Buffer *buf)
 Shorten a mailbox path using '~' or '='. More...
 
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. More...
 
void mutt_save_path (char *buf, size_t buflen, const struct Address *addr)
 Turn an email address into a filename (for saving) More...
 
void mutt_buffer_save_path (struct Buffer *dest, const struct Address *a)
 Make a safe filename from an email address. More...
 
void mutt_safe_path (struct Buffer *dest, const struct Address *a)
 Make a safe filename from an email address. More...
 
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 -. More...
 
FILE * mutt_open_read (const char *path, pid_t *thepid)
 Run a command to read from. More...
 
int mutt_save_confirm (const char *s, struct stat *st)
 Ask the user to save. More...
 
void mutt_sleep (short s)
 Sleep for a while. More...
 
const char * mutt_make_version (void)
 Generate the NeoMutt version string. More...
 
void mutt_encode_path (struct Buffer *buf, const char *src)
 Convert a path to 'us-ascii'. More...
 
int mutt_set_xdg_path (enum XdgType type, struct Buffer *buf)
 Find an XDG path or its fallback. More...
 
void mutt_get_parent_path (const char *path, char *buf, size_t buflen)
 Find the parent of a path (or mailbox) More...
 
int mutt_inbox_cmp (const char *a, const char *b)
 Do two folders share the same path and one is an inbox. More...
 
void mutt_buffer_sanitize_filename (struct Buffer *buf, const char *path, short slash)
 Replace unsafe characters in a filename. More...
 
void mutt_str_pretty_size (char *buf, size_t buflen, size_t num)
 Display an abbreviated size, like 3.4K. More...
 
void add_to_stailq (struct ListHead *head, const char *str)
 Add a string to a list. More...
 
void remove_from_stailq (struct ListHead *head, const char *str)
 Remove an item, matching a string, from a List. More...
 

Variables

static const char * xdg_env_vars []
 
static const char * xdg_defaults []
 

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

85{
86 if (!(buf->data && (buf->data[0] != '\0')))
87 {
89 }
90 else
91 {
92 struct Buffer *prefix = mutt_buffer_pool_get();
93 mutt_buffer_strcpy(prefix, buf->data);
94 mutt_file_sanitize_filename(prefix->data, true);
95 const char *const c_tmpdir = cs_subset_path(NeoMutt->sub, "tmpdir");
96 mutt_buffer_printf(buf, "%s/%s", NONULL(c_tmpdir), mutt_buffer_string(prefix));
97
98 struct stat st = { 0 };
99 if ((lstat(mutt_buffer_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 mutt_buffer_mktemp_pfx_sfx(buf, prefix->data, suffix);
109
110 out:
112 }
113}
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:327
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:647
#define mutt_buffer_mktemp_pfx_sfx(buf, prefix, suffix)
Definition: muttlib.h:75
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#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:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ 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 123 of file muttlib.c.

124{
125 return mutt_expand_path_regex(buf, buflen, false);
126}
char * mutt_expand_path_regex(char *buf, size_t buflen, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:336
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_expand_path_regex()

void mutt_buffer_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 135 of file muttlib.c.

136{
137 const char *s = NULL;
138 const char *tail = "";
139
140 bool recurse = false;
141
142 struct Buffer *p = mutt_buffer_pool_get();
143 struct Buffer *q = mutt_buffer_pool_get();
144 struct Buffer *tmp = mutt_buffer_pool_get();
145
146 do
147 {
148 recurse = false;
149 s = mutt_buffer_string(buf);
150
151 switch (*s)
152 {
153 case '~':
154 {
155 if ((s[1] == '/') || (s[1] == '\0'))
156 {
158 tail = s + 1;
159 }
160 else
161 {
162 char *t = strchr(s + 1, '/');
163 if (t)
164 *t = '\0';
165
166 struct passwd *pw = getpwnam(s + 1);
167 if (pw)
168 {
169 mutt_buffer_strcpy(p, pw->pw_dir);
170 if (t)
171 {
172 *t = '/';
173 tail = t;
174 }
175 else
176 tail = "";
177 }
178 else
179 {
180 /* user not found! */
181 if (t)
182 *t = '/';
184 tail = s;
185 }
186 }
187 break;
188 }
189
190 case '=':
191 case '+':
192 {
193 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
194 enum MailboxType mb_type = mx_path_probe(c_folder);
195
196 /* if folder = {host} or imap[s]://host/: don't append slash */
197 if ((mb_type == MUTT_IMAP) && ((c_folder[strlen(c_folder) - 1] == '}') ||
198 (c_folder[strlen(c_folder) - 1] == '/')))
199 {
200 mutt_buffer_strcpy(p, NONULL(c_folder));
201 }
202 else if (mb_type == MUTT_NOTMUCH)
203 mutt_buffer_strcpy(p, NONULL(c_folder));
204 else if (c_folder && (c_folder[strlen(c_folder) - 1] == '/'))
205 mutt_buffer_strcpy(p, NONULL(c_folder));
206 else
207 mutt_buffer_printf(p, "%s/", NONULL(c_folder));
208
209 tail = s + 1;
210 break;
211 }
212
213 /* elm compatibility, @ expands alias to user name */
214
215 case '@':
216 {
217 struct AddressList *al = alias_lookup(s + 1);
218 if (al && !TAILQ_EMPTY(al))
219 {
220 struct Email *e = email_new();
221 e->env = mutt_env_new();
222 mutt_addrlist_copy(&e->env->from, al, false);
223 mutt_addrlist_copy(&e->env->to, al, false);
224
225 /* TODO: fix mutt_default_save() to use Buffer */
227 mutt_default_save(p->data, p->dsize, e);
229
230 email_free(&e);
231 /* Avoid infinite recursion if the resulting folder starts with '@' */
232 if (*p->data != '@')
233 recurse = true;
234
235 tail = "";
236 }
237 break;
238 }
239
240 case '>':
241 {
242 const char *const c_mbox = cs_subset_string(NeoMutt->sub, "mbox");
243 mutt_buffer_strcpy(p, c_mbox);
244 tail = s + 1;
245 break;
246 }
247
248 case '<':
249 {
250 const char *const c_record = cs_subset_string(NeoMutt->sub, "record");
251 mutt_buffer_strcpy(p, c_record);
252 tail = s + 1;
253 break;
254 }
255
256 case '!':
257 {
258 if (s[1] == '!')
259 {
261 tail = s + 2;
262 }
263 else
264 {
265 const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
266 mutt_buffer_strcpy(p, c_spool_file);
267 tail = s + 1;
268 }
269 break;
270 }
271
272 case '-':
273 {
275 tail = s + 1;
276 break;
277 }
278
279 case '^':
280 {
282 tail = s + 1;
283 break;
284 }
285
286 default:
287 {
289 tail = s;
290 }
291 }
292
293 if (regex && *(mutt_buffer_string(p)) && !recurse)
294 {
296 mutt_buffer_printf(tmp, "%s%s", mutt_buffer_string(q), tail);
297 }
298 else
299 mutt_buffer_printf(tmp, "%s%s", mutt_buffer_string(p), tail);
300
301 mutt_buffer_copy(buf, tmp);
302 } while (recurse);
303
307
308#ifdef USE_IMAP
309 /* Rewrite IMAP path in canonical form - aids in string comparisons of
310 * folders. May possibly fail, in which case buf should be the same. */
312 imap_expand_path(buf);
313#endif
314}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:737
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:280
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:275
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:189
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:462
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
char * HomeDir
User's home directory.
Definition: mutt_globals.h:49
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:666
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2400
void mutt_default_save(char *path, size_t pathlen, struct Email *e)
Find the default save path for an email.
Definition: hook.c:737
int imap_expand_path(struct Buffer *buf)
Buffer wrapper around imap_path_canon()
Definition: imap.c:2440
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:40
char * LastFolder
Previously selected mailbox.
Definition: mutt_globals.h:55
char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:54
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1327
#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:

◆ mutt_buffer_expand_path()

void mutt_buffer_expand_path ( struct Buffer buf)

Create the canonical path.

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

Definition at line 322 of file muttlib.c.

323{
325}
void mutt_buffer_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:135
+ 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 336 of file muttlib.c.

337{
338 struct Buffer *tmp = mutt_buffer_pool_get();
339
340 mutt_buffer_addstr(tmp, NONULL(buf));
342 mutt_str_copy(buf, mutt_buffer_string(tmp), buflen);
343
345
346 return buf;
347}
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:233
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:652
+ 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 361 of file muttlib.c.

362{
363 regmatch_t pat_match[1];
364 size_t pwnl;
365 char *p = NULL;
366
367 if (!pw || !pw->pw_gecos)
368 return NULL;
369
370 memset(dest, 0, destlen);
371
372 const struct Regex *c_gecos_mask = cs_subset_regex(NeoMutt->sub, "gecos_mask");
373 if (mutt_regex_capture(c_gecos_mask, pw->pw_gecos, 1, pat_match))
374 {
375 mutt_str_copy(dest, pw->pw_gecos + pat_match[0].rm_so,
376 MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
377 }
378 else if ((p = strchr(pw->pw_gecos, ',')))
379 mutt_str_copy(dest, pw->pw_gecos, MIN(destlen, p - pw->pw_gecos + 1));
380 else
381 mutt_str_copy(dest, pw->pw_gecos, destlen);
382
383 pwnl = strlen(pw->pw_name);
384
385 for (int idx = 0; dest[idx]; idx++)
386 {
387 if (dest[idx] == '&')
388 {
389 memmove(&dest[idx + pwnl], &dest[idx + 1],
390 MAX((ssize_t) (destlen - idx - pwnl - 1), 0));
391 memcpy(&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl));
392 dest[idx] = toupper((unsigned char) dest[idx]);
393 }
394 }
395
396 return dest;
397}
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:243
#define MIN(a, b)
Definition: memory.h:31
#define MAX(a, b)
Definition: memory.h:30
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:614
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 405 of file muttlib.c.

406{
407 switch (m->type)
408 {
409 case TYPE_TEXT:
410 if (mutt_istr_equal("plain", m->subtype))
411 return false;
412 break;
413 case TYPE_APPLICATION:
415 return false;
417 return false;
418 break;
419
420 case TYPE_MULTIPART:
421 case TYPE_MESSAGE:
422 return false;
423 }
424
425 return true;
426}
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:544
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:601
@ 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:819
#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 433 of file muttlib.c.

434{
435 int t = b->type;
436 char *s = b->subtype;
437
439 return false;
440
441 if (t == TYPE_TEXT)
442 return true;
443
444 if (t == TYPE_MESSAGE)
445 {
446 if (mutt_istr_equal("delivery-status", s))
447 return true;
448 }
449
450 if (((WithCrypto & APPLICATION_PGP) != 0) && (t == TYPE_APPLICATION))
451 {
452 if (mutt_istr_equal("pgp-keys", s))
453 return true;
454 }
455
456 return false;
457}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_mktemp_full()

void mutt_buffer_mktemp_full ( struct Buffer buf,
const char *  prefix,
const char *  suffix,
const char *  src,
int  line 
)

Create a temporary file.

Parameters
bufBuffer for result
prefixPrefix for filename
suffixSuffix for filename
srcSource file of caller
lineSource line number of caller

Definition at line 467 of file muttlib.c.

469{
470 const char *const c_tmpdir = cs_subset_path(NeoMutt->sub, "tmpdir");
471 mutt_buffer_printf(buf, "%s/%s-%s-%d-%d-%" PRIu64 "%s%s", NONULL(c_tmpdir),
472 NONULL(prefix), NONULL(ShortHostname), (int) getuid(),
473 (int) getpid(), mutt_rand64(), suffix ? "." : "", NONULL(suffix));
474
475 mutt_debug(LL_DEBUG3, "%s:%d: mutt_mktemp returns \"%s\"\n", src, line,
476 mutt_buffer_string(buf));
477 if (unlink(mutt_buffer_string(buf)) && (errno != ENOENT))
478 {
479 mutt_debug(LL_DEBUG1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src,
480 line, mutt_buffer_string(buf), strerror(errno), errno);
481 }
482}
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:50
uint64_t mutt_rand64(void)
Create a 64-bit random number.
Definition: random.c:129
+ Here is the call graph for this function:

◆ mutt_mktemp_full()

void mutt_mktemp_full ( char *  buf,
size_t  buflen,
const char *  prefix,
const char *  suffix,
const char *  src,
int  line 
)

Create a temporary filename.

Parameters
bufBuffer for result
buflenLength of buffer
prefixPrefix for filename
suffixSuffix for filename
srcSource file of caller
lineSource line number of caller
Note
This doesn't create the file, only the name

Definition at line 495 of file muttlib.c.

497{
498 const char *const c_tmpdir = cs_subset_path(NeoMutt->sub, "tmpdir");
499 size_t n = snprintf(buf, buflen, "%s/%s-%s-%d-%d-%" PRIu64 "%s%s", NONULL(c_tmpdir),
500 NONULL(prefix), NONULL(ShortHostname), (int) getuid(),
501 (int) getpid(), mutt_rand64(), suffix ? "." : "", NONULL(suffix));
502 if (n >= buflen)
503 {
504 mutt_debug(LL_DEBUG1, "%s:%d: ERROR: insufficient buffer space to hold temporary filename! buflen=%zu but need %zu\n",
505 src, line, buflen, n);
506 }
507 mutt_debug(LL_DEBUG3, "%s:%d: mutt_mktemp returns \"%s\"\n", src, line, buf);
508 if ((unlink(buf) != 0) && (errno != ENOENT))
509 {
510 mutt_debug(LL_DEBUG1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src,
511 line, buf, strerror(errno), errno);
512 }
513}
+ Here is the call 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 522 of file muttlib.c.

523{
524 if (!buf)
525 return;
526
527 char *p = buf, *q = buf;
528 size_t len;
529 enum UrlScheme scheme;
530 char tmp[PATH_MAX] = { 0 };
531
532 scheme = url_check_scheme(buf);
533
534 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
535 if ((scheme == U_IMAP) || (scheme == U_IMAPS))
536 {
537 imap_pretty_mailbox(buf, buflen, c_folder);
538 return;
539 }
540
541 if (scheme == U_NOTMUCH)
542 return;
543
544 /* if buf is an url, only collapse path component */
545 if (scheme != U_UNKNOWN)
546 {
547 p = strchr(buf, ':') + 1;
548 if (mutt_strn_equal(p, "//", 2))
549 q = strchr(p + 2, '/');
550 if (!q)
551 q = strchr(p, '\0');
552 p = q;
553 }
554
555 /* cleanup path */
556 if (strstr(p, "//") || strstr(p, "/./"))
557 {
558 /* first attempt to collapse the pathname, this is more
559 * lightweight than realpath() and doesn't resolve links */
560 while (*p)
561 {
562 if ((p[0] == '/') && (p[1] == '/'))
563 {
564 *q++ = '/';
565 p += 2;
566 }
567 else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
568 {
569 *q++ = '/';
570 p += 3;
571 }
572 else
573 *q++ = *p++;
574 }
575 *q = '\0';
576 }
577 else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
578 realpath(p, tmp))
579 {
580 mutt_str_copy(p, tmp, buflen - (p - buf));
581 }
582
583 if ((len = mutt_str_startswith(buf, c_folder)) && (buf[len] == '/'))
584 {
585 *buf++ = '=';
586 memmove(buf, buf + len, mutt_str_len(buf + len) + 1);
587 }
588 else if ((len = mutt_str_startswith(buf, HomeDir)) && (buf[len] == '/'))
589 {
590 *buf++ = '~';
591 memmove(buf, buf + len - 1, mutt_str_len(buf + len - 1) + 1);
592 }
593}
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:589
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:496
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:227
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition: url.c:221
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:

◆ mutt_buffer_pretty_mailbox()

void mutt_buffer_pretty_mailbox ( struct Buffer buf)

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

Parameters
bufBuffer containing Mailbox name

Definition at line 599 of file muttlib.c.

600{
601 if (!buf || !buf->data)
602 return;
603 /* This reduces the size of the Buffer, so we can pass it through.
604 * We adjust the size just to make sure buf->data is not NULL though */
606 mutt_pretty_mailbox(buf->data, buf->dsize);
608}
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:522
+ 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 621 of file muttlib.c.

623{
624 struct stat st = { 0 };
625
626 mutt_buffer_strcpy(fname, path);
627 if (access(mutt_buffer_string(fname), F_OK) != 0)
628 return 0;
629 if (stat(mutt_buffer_string(fname), &st) != 0)
630 return -1;
631 if (S_ISDIR(st.st_mode))
632 {
633 enum QuadOption ans = MUTT_NO;
634 if (directory)
635 {
636 switch (mutt_multi_choice
637 /* L10N: Means "The path you specified as the destination file is a directory."
638 See the msgid "Save to file: " (alias.c, recvattach.c)
639 These three letters correspond to the choices in the string. */
640 (_("File is a directory, save under it: (y)es, (n)o, (a)ll?"), _("yna")))
641 {
642 case 3: /* all */
643 mutt_str_replace(directory, mutt_buffer_string(fname));
644 break;
645 case 1: /* yes */
646 FREE(directory);
647 break;
648 case -1: /* abort */
649 FREE(directory);
650 return -1;
651 case 2: /* no */
652 FREE(directory);
653 return 1;
654 }
655 }
656 /* L10N: Means "The path you specified as the destination file is a directory."
657 See the msgid "Save to file: " (alias.c, recvattach.c) */
658 else if ((ans = mutt_yesorno(_("File is a directory, save under it?"), MUTT_YES)) != MUTT_YES)
659 return (ans == MUTT_NO) ? 1 : -1;
660
661 struct Buffer *tmp = mutt_buffer_pool_get();
663 if ((mutt_buffer_get_field(_("File under directory: "), tmp, MUTT_COMP_FILE | MUTT_COMP_CLEAR,
664 false, NULL, NULL, NULL) != 0) ||
666 {
668 return (-1);
669 }
672 }
673
674 if ((*opt == MUTT_SAVE_NO_FLAGS) && (access(mutt_buffer_string(fname), F_OK) == 0))
675 {
676 char buf[4096] = { 0 };
677 snprintf(buf, sizeof(buf), "%s - %s", mutt_buffer_string(fname),
678 // L10N: Options for: File %s exists, (o)verwrite, (a)ppend, or (c)ancel?
679 _("File exists, (o)verwrite, (a)ppend, or (c)ancel?"));
680 switch (mutt_multi_choice(buf, _("oac")))
681 {
682 case -1: /* abort */
683 return -1;
684 case 3: /* cancel */
685 return 1;
686
687 case 2: /* append */
688 *opt = MUTT_SAVE_APPEND;
689 break;
690 case 1: /* overwrite */
691 *opt = MUTT_SAVE_OVERWRITE;
692 break;
693 }
694 }
695 return 0;
696}
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:260
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:389
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: window.c:180
#define FREE(x)
Definition: memory.h:43
#define _(a)
Definition: message.h:28
const char * mutt_path_basename(const char *f)
Find the last component for a pathname.
Definition: path.c:329
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
#define MUTT_COMP_FILE
File completion (in browser)
Definition: mutt.h:55
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:62
@ MUTT_SAVE_APPEND
Append to existing file.
Definition: mutt_attach.h:58
@ MUTT_SAVE_OVERWRITE
Overwrite existing file.
Definition: mutt_attach.h:59
@ MUTT_SAVE_NO_FLAGS
No flags set.
Definition: mutt_attach.h:57
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 mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:194
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: question.c:54
+ 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 707 of file muttlib.c.

708{
709 if (addr && addr->mailbox)
710 {
711 mutt_str_copy(buf, addr->mailbox, buflen);
712 const bool c_save_address = cs_subset_bool(NeoMutt->sub, "save_address");
713 if (!c_save_address)
714 {
715 char *p = strpbrk(buf, "%@");
716 if (p)
717 *p = '\0';
718 }
719 mutt_str_lower(buf);
720 }
721 else
722 *buf = '\0';
723}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
Definition: string.c:384
char * 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:

◆ mutt_buffer_save_path()

void mutt_buffer_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 730 of file muttlib.c.

731{
732 if (a && a->mailbox)
733 {
734 mutt_buffer_strcpy(dest, a->mailbox);
735 const bool c_save_address = cs_subset_bool(NeoMutt->sub, "save_address");
736 if (!c_save_address)
737 {
738 char *p = strpbrk(dest->data, "%@");
739 if (p)
740 {
741 *p = '\0';
743 }
744 }
745 mutt_str_lower(dest->data);
746 }
747 else
748 mutt_buffer_reset(dest);
749}
+ 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 758 of file muttlib.c.

759{
760 mutt_buffer_save_path(dest, a);
761 for (char *p = dest->data; *p; p++)
762 if ((*p == '/') || IS_SPACE(*p) || !IsPrint((unsigned char) *p))
763 *p = '_';
764}
#define IsPrint(ch)
Definition: mbyte.h:38
void mutt_buffer_save_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
Definition: muttlib.c:730
#define IS_SPACE(ch)
Definition: string2.h:38
+ 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 1311 of file muttlib.c.

1312{
1313 FILE *fp = NULL;
1314 struct stat st = { 0 };
1315
1316 size_t len = mutt_str_len(path);
1317 if (len == 0)
1318 {
1319 return NULL;
1320 }
1321
1322 if (path[len - 1] == '|')
1323 {
1324 /* read from a pipe */
1325
1326 char *p = mutt_str_dup(path);
1327
1328 p[len - 1] = 0;
1329 mutt_endwin();
1330 *thepid = filter_create(p, NULL, &fp, NULL);
1331 FREE(&p);
1332 }
1333 else
1334 {
1335 if (stat(path, &st) < 0)
1336 return NULL;
1337 if (S_ISDIR(st.st_mode))
1338 {
1339 errno = EINVAL;
1340 return NULL;
1341 }
1342 fp = fopen(path, "r");
1343 *thepid = -1;
1344 }
1345 return fp;
1346}
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:354
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
+ 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 1356 of file muttlib.c.

1357{
1358 int rc = 0;
1359
1360 enum MailboxType type = mx_path_probe(s);
1361
1362#ifdef USE_POP
1363 if (type == MUTT_POP)
1364 {
1365 mutt_error(_("Can't save message to POP mailbox"));
1366 return 1;
1367 }
1368#endif
1369
1370 if ((type != MUTT_MAILBOX_ERROR) && (type != MUTT_UNKNOWN) && (mx_access(s, W_OK) == 0))
1371 {
1372 const bool c_confirm_append = cs_subset_bool(NeoMutt->sub, "confirm_append");
1373 if (c_confirm_append)
1374 {
1375 struct Buffer *tmp = mutt_buffer_pool_get();
1376 mutt_buffer_printf(tmp, _("Append messages to %s?"), s);
1378 if (ans == MUTT_NO)
1379 rc = 1;
1380 else if (ans == MUTT_ABORT)
1381 rc = -1;
1383 }
1384 }
1385
1386#ifdef USE_NNTP
1387 if (type == MUTT_NNTP)
1388 {
1389 mutt_error(_("Can't save message to news server"));
1390 return 0;
1391 }
1392#endif
1393
1394 if (stat(s, st) != -1)
1395 {
1396 if (type == MUTT_MAILBOX_ERROR)
1397 {
1398 mutt_error(_("%s is not a mailbox"), s);
1399 return 1;
1400 }
1401 }
1402 else if (type != MUTT_IMAP)
1403 {
1404 st->st_mtime = 0;
1405 st->st_atime = 0;
1406
1407 /* pathname does not exist */
1408 if (errno == ENOENT)
1409 {
1410 const bool c_confirm_create = cs_subset_bool(NeoMutt->sub, "confirm_create");
1411 if (c_confirm_create)
1412 {
1413 struct Buffer *tmp = mutt_buffer_pool_get();
1414 mutt_buffer_printf(tmp, _("Create %s?"), s);
1416 if (ans == MUTT_NO)
1417 rc = 1;
1418 else if (ans == MUTT_ABORT)
1419 rc = -1;
1421 }
1422
1423 /* user confirmed with MUTT_YES or set `$confirm_create` */
1424 if (rc == 0)
1425 {
1426 /* create dir recursively */
1427 char *tmp_path = mutt_path_dirname(s);
1428 if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
1429 {
1430 /* report failure & abort */
1431 mutt_perror(s);
1432 FREE(&tmp_path);
1433 return 1;
1434 }
1435 FREE(&tmp_path);
1436 }
1437 }
1438 else
1439 {
1440 mutt_perror(s);
1441 return 1;
1442 }
1443 }
1444
1446 return rc;
1447}
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:930
#define mutt_error(...)
Definition: logging.h:87
#define mutt_perror(...)
Definition: logging.h:88
@ 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(void)
Clear the text in the Message Window.
Definition: msgwin.c:249
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final '/'.
Definition: path.c:376
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
Definition: mx.c:184
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition: quad.h:37
+ 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 1455 of file muttlib.c.

1456{
1457 const short c_sleep_time = cs_subset_number(NeoMutt->sub, "sleep_time");
1458 if (c_sleep_time > s)
1459 sleep(c_sleep_time);
1460 else if (s)
1461 sleep(s);
1462}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
+ 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 1470 of file muttlib.c.

1471{
1472 static char vstring[256];
1473 snprintf(vstring, sizeof(vstring), "NeoMutt %s%s", PACKAGE_VERSION, GitVer);
1474 return vstring;
1475}
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 1484 of file muttlib.c.

1485{
1486 char *p = mutt_str_dup(src);
1487 const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
1488 int rc = mutt_ch_convert_string(&p, c_charset, "us-ascii", MUTT_ICONV_NO_FLAGS);
1489 size_t len = mutt_buffer_strcpy(buf, (rc == 0) ? NONULL(p) : NONULL(src));
1490
1491 /* convert the path to POSIX "Portable Filename Character Set" */
1492 for (size_t i = 0; i < len; i++)
1493 {
1494 if (!isalnum(buf->data[i]) && !strchr("/.-_", buf->data[i]))
1495 {
1496 buf->data[i] = '_';
1497 }
1498 }
1499 FREE(&p);
1500}
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:752
#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 1510 of file muttlib.c.

1511{
1512 const char *xdg_env = mutt_str_getenv(xdg_env_vars[type]);
1513 char *xdg = xdg_env ? mutt_str_dup(xdg_env) : mutt_str_dup(xdg_defaults[type]);
1514 char *x = xdg; /* mutt_str_sep() changes xdg, so free x instead later */
1515 char *token = NULL;
1516 int rc = 0;
1517
1518 while ((token = mutt_str_sep(&xdg, ":")))
1519 {
1520 if (mutt_buffer_printf(buf, "%s/%s/neomuttrc", token, PACKAGE) < 0)
1521 continue;
1523 if (access(mutt_buffer_string(buf), F_OK) == 0)
1524 {
1525 rc = 1;
1526 break;
1527 }
1528
1529 if (mutt_buffer_printf(buf, "%s/%s/Muttrc", token, PACKAGE) < 0)
1530 continue;
1532 if (access(mutt_buffer_string(buf), F_OK) == 0)
1533 {
1534 rc = 1;
1535 break;
1536 }
1537 }
1538
1539 FREE(&x);
1540 return rc;
1541}
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:927
char * mutt_str_sep(char **stringp, const char *delim)
Find first occurance of any of delim characters in *stringp.
Definition: string.c:183
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
static const char * xdg_env_vars[]
Definition: muttlib.c:66
static const char * xdg_defaults[]
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 1549 of file muttlib.c.

1550{
1551 enum MailboxType mb_type = mx_path_probe(path);
1552
1553 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1554 if (mb_type == MUTT_IMAP)
1555 imap_get_parent_path(path, buf, buflen);
1556 else if (mb_type == MUTT_NOTMUCH)
1557 mutt_str_copy(buf, c_folder, buflen);
1558 else
1559 {
1560 mutt_str_copy(buf, path, buflen);
1561 int n = mutt_str_len(buf);
1562 if (n == 0)
1563 return;
1564
1565 /* remove any final trailing '/' */
1566 if (buf[n - 1] == '/')
1567 buf[n - 1] = '\0';
1568
1569 /* Remove everything until the next slash */
1570 for (n--; ((n >= 0) && (buf[n] != '/')); n--)
1571 ; // do nothing
1572
1573 if (n > 0)
1574 buf[n] = '\0';
1575 else
1576 {
1577 buf[0] = '/';
1578 buf[1] = '\0';
1579 }
1580 }
1581}
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
Definition: util.c:161
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_inbox_cmp()

int mutt_inbox_cmp ( const char *  a,
const char *  b 
)

Do two folders share the same path and one is an inbox.

Parameters
aFirst path
bSecond path
Return values
-1a is INBOX of b
0None is INBOX
1b is INBOX for a

This function compares two folder paths. It first looks for the position of the last common '/' character. If a valid position is found and it's not the last character in any of the two paths, the remaining parts of the paths are compared (case insensitively) with the string "INBOX". If one of the two paths matches, it's reported as being less than the other and the function returns -1 (a < b) or 1 (a > b). If no paths match the requirements, the two paths are considered equivalent and this function returns 0.

Examples:

  • mutt_inbox_cmp("/foo/bar", "/foo/baz") --> 0
  • mutt_inbox_cmp("/foo/bar/", "/foo/bar/inbox") --> 0
  • mutt_inbox_cmp("/foo/bar/sent", "/foo/bar/inbox") --> 1
  • mutt_inbox_cmp("=INBOX", "=Drafts") --> -1

Definition at line 1605 of file muttlib.c.

1606{
1607 /* fast-track in case the paths have been mutt_pretty_mailbox'ified */
1608 if ((a[0] == '+') && (b[0] == '+'))
1609 {
1610 return mutt_istr_equal(a + 1, "inbox") ? -1 :
1611 mutt_istr_equal(b + 1, "inbox") ? 1 :
1612 0;
1613 }
1614
1615 const char *a_end = strrchr(a, '/');
1616 const char *b_end = strrchr(b, '/');
1617
1618 /* If one path contains a '/', but not the other */
1619 if ((!a_end) ^ (!b_end))
1620 return 0;
1621
1622 /* If neither path contains a '/' */
1623 if (!a_end)
1624 return 0;
1625
1626 /* Compare the subpaths */
1627 size_t a_len = a_end - a;
1628 size_t b_len = b_end - b;
1629 size_t min = MIN(a_len, b_len);
1630 int same = (a[min] == '/') && (b[min] == '/') && (a[min + 1] != '\0') &&
1631 (b[min + 1] != '\0') && mutt_istrn_equal(a, b, min);
1632
1633 if (!same)
1634 return 0;
1635
1636 if (mutt_istr_equal(&a[min + 1], "inbox"))
1637 return -1;
1638
1639 if (mutt_istr_equal(&b[min + 1], "inbox"))
1640 return 1;
1641
1642 return 0;
1643}
bool mutt_istrn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:524
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_sanitize_filename()

void mutt_buffer_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 1651 of file muttlib.c.

1652{
1653 if (!buf || !path)
1654 return;
1655
1656 mutt_buffer_reset(buf);
1657
1658 for (; *path; path++)
1659 {
1660 if ((slash && (*path == '/')) || !strchr(filename_safe_chars, *path))
1661 mutt_buffer_addch(buf, '_');
1662 else
1663 mutt_buffer_addch(buf, *path);
1664 }
1665}
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:248
const char filename_safe_chars[]
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 1673 of file muttlib.c.

1674{
1675 if (!buf || (buflen == 0))
1676 return;
1677
1678 const bool c_size_show_bytes = cs_subset_bool(NeoMutt->sub, "size_show_bytes");
1679 const bool c_size_show_fractions = cs_subset_bool(NeoMutt->sub, "size_show_fractions");
1680 const bool c_size_show_mb = cs_subset_bool(NeoMutt->sub, "size_show_mb");
1681 const bool c_size_units_on_left = cs_subset_bool(NeoMutt->sub, "size_units_on_left");
1682
1683 if (c_size_show_bytes && (num < 1024))
1684 {
1685 snprintf(buf, buflen, "%d", (int) num);
1686 }
1687 else if (num == 0)
1688 {
1689 mutt_str_copy(buf, c_size_units_on_left ? "K0" : "0K", buflen);
1690 }
1691 else if (c_size_show_fractions && (num < 10189)) /* 0.1K - 9.9K */
1692 {
1693 snprintf(buf, buflen, c_size_units_on_left ? "K%3.1f" : "%3.1fK",
1694 (num < 103) ? 0.1 : (num / 1024.0));
1695 }
1696 else if (!c_size_show_mb || (num < 1023949)) /* 10K - 999K */
1697 {
1698 /* 51 is magic which causes 10189/10240 to be rounded up to 10 */
1699 snprintf(buf, buflen, c_size_units_on_left ? ("K%zu") : ("%zuK"), (num + 51) / 1024);
1700 }
1701 else if (c_size_show_fractions && (num < 10433332)) /* 1.0M - 9.9M */
1702 {
1703 snprintf(buf, buflen, c_size_units_on_left ? "M%3.1f" : "%3.1fM", num / 1048576.0);
1704 }
1705 else /* 10M+ */
1706 {
1707 /* (10433332 + 52428) / 1048576 = 10 */
1708 snprintf(buf, buflen, c_size_units_on_left ? ("M%zu") : ("%zuM"), (num + 52428) / 1048576);
1709 }
1710}
+ 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 1719 of file muttlib.c.

1720{
1721 /* don't add a NULL or empty string to the list */
1722 if (!str || (*str == '\0'))
1723 return;
1724
1725 /* check to make sure the item is not already on this list */
1726 struct ListNode *np = NULL;
1727 STAILQ_FOREACH(np, head, entries)
1728 {
1729 if (mutt_istr_equal(str, np->data))
1730 {
1731 return;
1732 }
1733 }
1735}
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 1744 of file muttlib.c.

1745{
1746 if (mutt_str_equal("*", str))
1747 mutt_list_free(head); /* "unCMD *" means delete all current entries */
1748 else
1749 {
1750 struct ListNode *np = NULL, *tmp = NULL;
1751 STAILQ_FOREACH_SAFE(np, head, entries, tmp)
1752 {
1753 if (mutt_istr_equal(str, np->data))
1754 {
1755 STAILQ_REMOVE(head, np, ListNode, entries);
1756 FREE(&np->data);
1757 FREE(&np);
1758 break;
1759 }
1760 }
1761 }
1762}
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:807
#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

◆ xdg_env_vars

const char* xdg_env_vars[]
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

Definition at line 66 of file muttlib.c.

◆ xdg_defaults

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

Definition at line 71 of file muttlib.c.