NeoMutt  2023-11-03-85-g512e01
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
muttlib.h File Reference

Some miscellaneous functions. More...

#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "attach/lib.h"
#include "format_flags.h"
+ Include dependency graph for muttlib.h:

Go to the source code of this file.

Functions

void mutt_adv_mktemp (struct Buffer *buf)
 Create a temporary file.
 
void buf_expand_path (struct Buffer *buf)
 Create the canonical path.
 
void buf_expand_path_regex (struct Buffer *buf, bool regex)
 Create the canonical path (with regex char escaping)
 
void buf_pretty_mailbox (struct Buffer *s)
 Shorten a mailbox path using '~' or '='.
 
void buf_sanitize_filename (struct Buffer *buf, const char *path, short slash)
 Replace unsafe characters in a filename.
 
void buf_save_path (struct Buffer *dest, const struct Address *a)
 Make a safe filename from an email address.
 
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_encode_path (struct Buffer *buf, const char *src)
 Convert a path to 'us-ascii'.
 
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 -.
 
char * mutt_expand_path (char *s, size_t slen)
 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.
 
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 -.
 
bool mutt_is_text_part (struct Body *b)
 Is this part of an email in plain text?
 
const char * mutt_make_version (void)
 Generate the NeoMutt version string.
 
bool mutt_needs_mailcap (struct Body *b)
 Does this type need a mailcap entry do display.
 
FILE * mutt_open_read (const char *path, pid_t *thepid)
 Run a command to read from.
 
void mutt_pretty_mailbox (char *buf, size_t buflen)
 Shorten a mailbox path using '~' or '='.
 
void mutt_safe_path (struct Buffer *dest, const struct Address *a)
 Make a safe filename from an email address.
 
int mutt_save_confirm (const char *s, struct stat *st)
 Ask the user to save.
 
void mutt_save_path (char *d, size_t dsize, const struct Address *a)
 Turn an email address into a filename (for saving)
 
void mutt_sleep (short s)
 Sleep for a while.
 
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.
 

Detailed Description

Some miscellaneous functions.

Authors
  • Richard Russon
  • 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.h.

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

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

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

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

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

◆ buf_pretty_mailbox()

void buf_pretty_mailbox ( struct Buffer buf)

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

Parameters
bufBuffer containing Mailbox name

Definition at line 556 of file muttlib.c.

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

1620{
1621 if (!buf || !path)
1622 return;
1623
1624 buf_reset(buf);
1625
1626 for (; *path; path++)
1627 {
1628 if ((slash && (*path == '/')) || !strchr(FilenameSafeChars, *path))
1629 buf_addch(buf, '_');
1630 else
1631 buf_addch(buf, *path);
1632 }
1633}
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:253
const char FilenameSafeChars[]
Set of characters <=0x7F that are safe to use in filenames.
Definition: file.c:61
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

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

691{
692 if (a && a->mailbox)
693 {
694 buf_copy(dest, a->mailbox);
695 const bool c_save_address = cs_subset_bool(NeoMutt->sub, "save_address");
696 if (!c_save_address)
697 {
698 char *p = strpbrk(dest->data, "%@");
699 if (p)
700 {
701 *p = '\0';
702 buf_fix_dptr(dest);
703 }
704 }
705 mutt_str_lower(dest->data);
706 }
707 else
708 {
709 buf_reset(dest);
710 }
711}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
Definition: string.c:385
struct Buffer * mailbox
Mailbox and host address.
Definition: address.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

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

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

◆ mutt_encode_path()

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

Convert a path to 'us-ascii'.

Parameters
bufBuffer for the result
srcPath to convert (OPTIONAL)

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

Definition at line 1447 of file muttlib.c.

1448{
1449 char *p = mutt_str_dup(src);
1450 int rc = mutt_ch_convert_string(&p, cc_charset(), "us-ascii", MUTT_ICONV_NO_FLAGS);
1451 size_t len = buf_strcpy(buf, (rc == 0) ? NONULL(p) : NONULL(src));
1452
1453 /* convert the path to POSIX "Portable Filename Character Set" */
1454 for (size_t i = 0; i < len; i++)
1455 {
1456 if (!isalnum(buf->data[i]) && !strchr("/.-_", buf->data[i]))
1457 {
1458 buf->data[i] = '_';
1459 }
1460 }
1461 FREE(&p);
1462}
const char * cc_charset(void)
Get the cached value of $charset.
Definition: config_cache.c:115
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:826
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:251
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_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 124 of file muttlib.c.

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

344{
345 struct Buffer *tmp = buf_pool_get();
346
347 buf_addstr(tmp, NONULL(buf));
348 buf_expand_path_regex(tmp, regex);
349 mutt_str_copy(buf, buf_string(tmp), buflen);
350
351 buf_pool_release(&tmp);
352
353 return buf;
354}
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:238
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:653
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_gecos_name()

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

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

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

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

Definition at line 368 of file muttlib.c.

369{
370 regmatch_t pat_match[1];
371 size_t pwnl;
372 char *p = NULL;
373
374 if (!pw || !pw->pw_gecos)
375 return NULL;
376
377 memset(dest, 0, destlen);
378
379 const struct Regex *c_gecos_mask = cs_subset_regex(NeoMutt->sub, "gecos_mask");
380 if (mutt_regex_capture(c_gecos_mask, pw->pw_gecos, 1, pat_match))
381 {
382 mutt_str_copy(dest, pw->pw_gecos + pat_match[0].rm_so,
383 MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
384 }
385 else if ((p = strchr(pw->pw_gecos, ',')))
386 {
387 mutt_str_copy(dest, pw->pw_gecos, MIN(destlen, p - pw->pw_gecos + 1));
388 }
389 else
390 {
391 mutt_str_copy(dest, pw->pw_gecos, destlen);
392 }
393
394 pwnl = strlen(pw->pw_name);
395
396 for (int idx = 0; dest[idx]; idx++)
397 {
398 if (dest[idx] == '&')
399 {
400 memmove(&dest[idx + pwnl], &dest[idx + 1],
401 MAX((ssize_t) (destlen - idx - pwnl - 1), 0));
402 memcpy(&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl));
403 dest[idx] = toupper((unsigned char) dest[idx]);
404 }
405 }
406
407 return dest;
408}
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:218
#define MIN(a, b)
Definition: memory.h:32
#define MAX(a, b)
Definition: memory.h:31
bool mutt_regex_capture(const struct Regex *regex, const char *str, size_t nmatch, regmatch_t matches[])
Match a regex against a string, with provided options.
Definition: regex.c:619
Cached regular expression.
Definition: regex3.h:89
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_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 1511 of file muttlib.c.

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

445{
446 int t = b->type;
447 char *s = b->subtype;
448
450 return false;
451
452 if (t == TYPE_TEXT)
453 return true;
454
455 if (t == TYPE_MESSAGE)
456 {
457 if (mutt_istr_equal("delivery-status", s))
458 return true;
459 }
460
461 if (((WithCrypto & APPLICATION_PGP) != 0) && (t == TYPE_APPLICATION))
462 {
463 if (mutt_istr_equal("pgp-keys", s))
464 return true;
465 }
466
467 return false;
468}
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:537
@ TYPE_MESSAGE
Type: 'message/*'.
Definition: mime.h:35
@ TYPE_APPLICATION
Type: 'application/*'.
Definition: mime.h:33
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:810
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:91
#define WithCrypto
Definition: lib.h:117
char * subtype
content-type subtype
Definition: body.h:60
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_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 1433 of file muttlib.c.

1434{
1435 static char vstring[256];
1436 snprintf(vstring, sizeof(vstring), "NeoMutt %s%s", PACKAGE_VERSION, GitVer);
1437 return vstring;
1438}
const char * GitVer

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

417{
418 switch (b->type)
419 {
420 case TYPE_TEXT:
421 if (mutt_istr_equal("plain", b->subtype))
422 return false;
423 break;
424 case TYPE_APPLICATION:
426 return false;
428 return false;
429 break;
430
431 case TYPE_MULTIPART:
432 case TYPE_MESSAGE:
433 return false;
434 }
435
436 return true;
437}
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:598
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:92
+ 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 1276 of file muttlib.c.

1277{
1278 FILE *fp = NULL;
1279 struct stat st = { 0 };
1280
1281 size_t len = mutt_str_len(path);
1282 if (len == 0)
1283 {
1284 return NULL;
1285 }
1286
1287 if (path[len - 1] == '|')
1288 {
1289 /* read from a pipe */
1290
1291 char *p = mutt_str_dup(path);
1292
1293 p[len - 1] = 0;
1294 mutt_endwin();
1295 *thepid = filter_create(p, NULL, &fp, NULL, EnvList);
1296 FREE(&p);
1297 }
1298 else
1299 {
1300 if (stat(path, &st) < 0)
1301 return NULL;
1302 if (S_ISDIR(st.st_mode))
1303 {
1304 errno = EINVAL;
1305 return NULL;
1306 }
1307 fp = fopen(path, "r");
1308 *thepid = -1;
1309 }
1310 return fp;
1311}
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:150
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, char **envlist)
Set up filter program.
Definition: filter.c:207
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:83
+ 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 477 of file muttlib.c.

478{
479 if (!buf)
480 return;
481
482 char *p = buf, *q = buf;
483 size_t len;
484 enum UrlScheme scheme;
485 char tmp[PATH_MAX] = { 0 };
486
487 scheme = url_check_scheme(buf);
488
489 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
490 if ((scheme == U_IMAP) || (scheme == U_IMAPS))
491 {
492 imap_pretty_mailbox(buf, buflen, c_folder);
493 return;
494 }
495
496 if (scheme == U_NOTMUCH)
497 return;
498
499 /* if buf is an url, only collapse path component */
500 if (scheme != U_UNKNOWN)
501 {
502 p = strchr(buf, ':') + 1;
503 if (mutt_strn_equal(p, "//", 2))
504 q = strchr(p + 2, '/');
505 if (!q)
506 q = strchr(p, '\0');
507 p = q;
508 }
509
510 /* cleanup path */
511 if (strstr(p, "//") || strstr(p, "/./"))
512 {
513 /* first attempt to collapse the pathname, this is more
514 * lightweight than realpath() and doesn't resolve links */
515 while (*p)
516 {
517 if ((p[0] == '/') && (p[1] == '/'))
518 {
519 *q++ = '/';
520 p += 2;
521 }
522 else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
523 {
524 *q++ = '/';
525 p += 3;
526 }
527 else
528 {
529 *q++ = *p++;
530 }
531 }
532 *q = '\0';
533 }
534 else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
535 realpath(p, tmp))
536 {
537 mutt_str_copy(p, tmp, buflen - (p - buf));
538 }
539
540 if ((len = mutt_str_startswith(buf, c_folder)) && (buf[len] == '/'))
541 {
542 *buf++ = '=';
543 memmove(buf, buf + len, mutt_str_len(buf + len) + 1);
544 }
545 else if ((len = mutt_str_startswith(buf, HomeDir)) && (buf[len] == '/'))
546 {
547 *buf++ = '~';
548 memmove(buf, buf + len - 1, mutt_str_len(buf + len - 1) + 1);
549 }
550}
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:579
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:497
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:228
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition: url.c:225
UrlScheme
All recognised Url types.
Definition: url.h:34
@ U_NOTMUCH
Url is notmuch://.
Definition: url.h:46
@ U_UNKNOWN
Url wasn't recognised.
Definition: url.h:35
@ U_FILE
Url is file://.
Definition: url.h:36
@ U_IMAP
Url is imap://.
Definition: url.h:39
@ U_IMAPS
Url is imaps://.
Definition: url.h:40
+ Here is the 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 720 of file muttlib.c.

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

1322{
1323 int rc = 0;
1324
1325 enum MailboxType type = mx_path_probe(s);
1326
1327 if (type == MUTT_POP)
1328 {
1329 mutt_error(_("Can't save message to POP mailbox"));
1330 return 1;
1331 }
1332
1333 if ((type != MUTT_MAILBOX_ERROR) && (type != MUTT_UNKNOWN) && (mx_access(s, W_OK) == 0))
1334 {
1335 const bool c_confirm_append = cs_subset_bool(NeoMutt->sub, "confirm_append");
1336 if (c_confirm_append)
1337 {
1338 struct Buffer *tmp = buf_pool_get();
1339 buf_printf(tmp, _("Append messages to %s?"), s);
1341 NeoMutt->sub, "confirm_append");
1342 if (ans == MUTT_NO)
1343 rc = 1;
1344 else if (ans == MUTT_ABORT)
1345 rc = -1;
1346 buf_pool_release(&tmp);
1347 }
1348 }
1349
1350 if (type == MUTT_NNTP)
1351 {
1352 mutt_error(_("Can't save message to news server"));
1353 return 0;
1354 }
1355
1356 if (stat(s, st) != -1)
1357 {
1358 if (type == MUTT_MAILBOX_ERROR)
1359 {
1360 mutt_error(_("%s is not a mailbox"), s);
1361 return 1;
1362 }
1363 }
1364 else if (type != MUTT_IMAP)
1365 {
1366 st->st_mtime = 0;
1367 st->st_atime = 0;
1368
1369 /* pathname does not exist */
1370 if (errno == ENOENT)
1371 {
1372 const bool c_confirm_create = cs_subset_bool(NeoMutt->sub, "confirm_create");
1373 if (c_confirm_create)
1374 {
1375 struct Buffer *tmp = buf_pool_get();
1376 buf_printf(tmp, _("Create %s?"), s);
1378 NeoMutt->sub, "confirm_create");
1379 if (ans == MUTT_NO)
1380 rc = 1;
1381 else if (ans == MUTT_ABORT)
1382 rc = -1;
1383 buf_pool_release(&tmp);
1384 }
1385
1386 /* user confirmed with MUTT_YES or set `$confirm_create` */
1387 if (rc == 0)
1388 {
1389 /* create dir recursively */
1390 char *tmp_path = mutt_path_dirname(s);
1391 if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
1392 {
1393 /* report failure & abort */
1394 mutt_perror("%s", s);
1395 FREE(&tmp_path);
1396 return 1;
1397 }
1398 FREE(&tmp_path);
1399 }
1400 }
1401 else
1402 {
1403 mutt_perror("%s", s);
1404 return 1;
1405 }
1406 }
1407
1408 msgwin_clear_text(NULL);
1409 return rc;
1410}
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:977
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_perror(...)
Definition: logging2.h:93
@ MUTT_MAILBOX_ERROR
Error occurred examining Mailbox.
Definition: mailbox.h:43
@ MUTT_POP
'POP3' Mailbox type
Definition: mailbox.h:52
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition: mailbox.h:49
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition: mailbox.h:44
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition: msgwin.c:516
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final '/'.
Definition: path.c:308
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
Definition: mx.c:166
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition: quad.h:37
enum QuadOption query_yesorno_help(const char *prompt, enum QuadOption def, struct ConfigSubset *sub, const char *name)
Ask the user a Yes/No question offering help.
Definition: question.c:345
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_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 665 of file muttlib.c.

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

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

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

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

1713{
1714 if (mutt_str_equal("*", str))
1715 {
1716 mutt_list_free(head); /* "unCMD *" means delete all current entries */
1717 }
1718 else
1719 {
1720 struct ListNode *np = NULL, *tmp = NULL;
1721 STAILQ_FOREACH_SAFE(np, head, entries, tmp)
1722 {
1723 if (mutt_istr_equal(str, np->data))
1724 {
1725 STAILQ_REMOVE(head, np, ListNode, entries);
1726 FREE(&np->data);
1727 FREE(&np);
1728 break;
1729 }
1730 }
1731 }
1732}
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:402
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
+ Here is the call graph for this function:
+ Here is the caller graph for this function: