NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
muttlib.h File Reference

Some miscellaneous functions. More...

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

Go to the source code of this file.

Macros

#define mutt_mktemp(buf, buflen)   mutt_mktemp_pfx_sfx(buf, buflen, "neomutt", NULL)
 
#define mutt_mktemp_pfx_sfx(buf, buflen, prefix, suffix)   mutt_mktemp_full(buf, buflen, prefix, suffix, __FILE__, __LINE__)
 
#define mutt_buffer_mktemp(buf)   mutt_buffer_mktemp_pfx_sfx(buf, "neomutt", NULL)
 
#define mutt_buffer_mktemp_pfx_sfx(buf, prefix, suffix)   mutt_buffer_mktemp_full(buf, prefix, suffix, __FILE__, __LINE__)
 

Functions

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

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.

Macro Definition Documentation

◆ mutt_mktemp

#define mutt_mktemp (   buf,
  buflen 
)    mutt_mktemp_pfx_sfx(buf, buflen, "neomutt", NULL)

Definition at line 71 of file muttlib.h.

◆ mutt_mktemp_pfx_sfx

#define mutt_mktemp_pfx_sfx (   buf,
  buflen,
  prefix,
  suffix 
)    mutt_mktemp_full(buf, buflen, prefix, suffix, __FILE__, __LINE__)

Definition at line 72 of file muttlib.h.

◆ mutt_buffer_mktemp

#define mutt_buffer_mktemp (   buf)    mutt_buffer_mktemp_pfx_sfx(buf, "neomutt", NULL)

Definition at line 74 of file muttlib.h.

◆ mutt_buffer_mktemp_pfx_sfx

#define mutt_buffer_mktemp_pfx_sfx (   buf,
  prefix,
  suffix 
)    mutt_buffer_mktemp_full(buf, prefix, suffix, __FILE__, __LINE__)

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

84 {
85  if (!(buf->data && (buf->data[0] != '\0')))
86  {
87  mutt_buffer_mktemp(buf);
88  }
89  else
90  {
91  struct Buffer *prefix = mutt_buffer_pool_get();
92  mutt_buffer_strcpy(prefix, buf->data);
93  mutt_file_sanitize_filename(prefix->data, true);
94  const char *const c_tmpdir = cs_subset_path(NeoMutt->sub, "tmpdir");
95  mutt_buffer_printf(buf, "%s/%s", NONULL(c_tmpdir), mutt_buffer_string(prefix));
96 
97  struct stat sb;
98  if ((lstat(mutt_buffer_string(buf), &sb) == -1) && (errno == ENOENT))
99  goto out;
100 
101  char *suffix = strchr(prefix->data, '.');
102  if (suffix)
103  {
104  *suffix = '\0';
105  suffix++;
106  }
107  mutt_buffer_mktemp_pfx_sfx(buf, prefix->data, suffix);
108 
109  out:
110  mutt_buffer_pool_release(&prefix);
111  }
112 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_buffer_mktemp_pfx_sfx(buf, prefix, suffix)
Definition: muttlib.h:75
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Container for Accounts, Notifications.
Definition: neomutt.h:36
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:618
char * data
Pointer to data.
Definition: buffer.h:35
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
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_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 468 of file muttlib.c.

470 {
471  const char *const c_tmpdir = cs_subset_path(NeoMutt->sub, "tmpdir");
472  mutt_buffer_printf(buf, "%s/%s-%s-%d-%d-%" PRIu64 "%s%s", NONULL(c_tmpdir),
473  NONULL(prefix), NONULL(ShortHostname), (int) getuid(),
474  (int) getpid(), mutt_rand64(), suffix ? "." : "", NONULL(suffix));
475 
476  mutt_debug(LL_DEBUG3, "%s:%d: mutt_mktemp returns \"%s\"\n", src, line,
477  mutt_buffer_string(buf));
478  if (unlink(mutt_buffer_string(buf)) && (errno != ENOENT))
479  {
480  mutt_debug(LL_DEBUG1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src,
481  line, mutt_buffer_string(buf), strerror(errno), errno);
482  }
483 }
#define NONULL(x)
Definition: string2.h:37
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
Container for Accounts, Notifications.
Definition: neomutt.h:36
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
uint64_t mutt_rand64(void)
Create a 64-bit random number.
Definition: random.c:130
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:46
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Log at debug level 3.
Definition: logging.h:42
+ Here is the call 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 {
324  mutt_buffer_expand_path_regex(buf, false);
325 }
void mutt_buffer_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:134
+ 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 134 of file muttlib.c.

135 {
136  const char *s = NULL;
137  const char *tail = "";
138 
139  bool recurse = false;
140 
141  struct Buffer *p = mutt_buffer_pool_get();
142  struct Buffer *q = mutt_buffer_pool_get();
143  struct Buffer *tmp = mutt_buffer_pool_get();
144 
145  do
146  {
147  recurse = false;
148  s = mutt_buffer_string(buf);
149 
150  switch (*s)
151  {
152  case '~':
153  {
154  if ((s[1] == '/') || (s[1] == '\0'))
155  {
157  tail = s + 1;
158  }
159  else
160  {
161  char *t = strchr(s + 1, '/');
162  if (t)
163  *t = '\0';
164 
165  struct passwd *pw = getpwnam(s + 1);
166  if (pw)
167  {
168  mutt_buffer_strcpy(p, pw->pw_dir);
169  if (t)
170  {
171  *t = '/';
172  tail = t;
173  }
174  else
175  tail = "";
176  }
177  else
178  {
179  /* user not found! */
180  if (t)
181  *t = '/';
183  tail = s;
184  }
185  }
186  break;
187  }
188 
189  case '=':
190  case '+':
191  {
192  const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
193  enum MailboxType mb_type = mx_path_probe(c_folder);
194 
195  /* if folder = {host} or imap[s]://host/: don't append slash */
196  if ((mb_type == MUTT_IMAP) && ((c_folder[strlen(c_folder) - 1] == '}') ||
197  (c_folder[strlen(c_folder) - 1] == '/')))
198  {
199  mutt_buffer_strcpy(p, NONULL(c_folder));
200  }
201  else if (mb_type == MUTT_NOTMUCH)
202  mutt_buffer_strcpy(p, NONULL(c_folder));
203  else if (c_folder && (c_folder[strlen(c_folder) - 1] == '/'))
204  mutt_buffer_strcpy(p, NONULL(c_folder));
205  else
206  mutt_buffer_printf(p, "%s/", NONULL(c_folder));
207 
208  tail = s + 1;
209  break;
210  }
211 
212  /* elm compatibility, @ expands alias to user name */
213 
214  case '@':
215  {
216  struct AddressList *al = alias_lookup(s + 1);
217  if (al && !TAILQ_EMPTY(al))
218  {
219  struct Email *e = email_new();
220  e->env = mutt_env_new();
221  mutt_addrlist_copy(&e->env->from, al, false);
222  mutt_addrlist_copy(&e->env->to, al, false);
223 
224  /* TODO: fix mutt_default_save() to use Buffer */
226  mutt_default_save(p->data, p->dsize, e);
228 
229  email_free(&e);
230  /* Avoid infinite recursion if the resulting folder starts with '@' */
231  if (*p->data != '@')
232  recurse = true;
233 
234  tail = "";
235  }
236  break;
237  }
238 
239  case '>':
240  {
241  const char *const c_mbox = cs_subset_string(NeoMutt->sub, "mbox");
242  mutt_buffer_strcpy(p, c_mbox);
243  tail = s + 1;
244  break;
245  }
246 
247  case '<':
248  {
249  const char *const c_record = cs_subset_string(NeoMutt->sub, "record");
250  mutt_buffer_strcpy(p, c_record);
251  tail = s + 1;
252  break;
253  }
254 
255  case '!':
256  {
257  if (s[1] == '!')
258  {
260  tail = s + 2;
261  }
262  else
263  {
264  const char *const c_spool_file =
265  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. */
311  if (imap_path_probe(mutt_buffer_string(buf), NULL) == MUTT_IMAP)
312  imap_expand_path(buf);
313 #endif
314 }
#define NONULL(x)
Definition: string2.h:37
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
The envelope/body of an email.
Definition: email.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer&#39;s contents to another Buffer.
Definition: buffer.c:445
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
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
String manipulation buffer.
Definition: buffer.h:33
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
void mutt_default_save(char *path, size_t pathlen, struct Email *e)
Find the default save path for an email.
Definition: hook.c:677
Container for Accounts, Notifications.
Definition: neomutt.h:36
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:45
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
size_t dsize
Length of data.
Definition: buffer.h:37
int imap_expand_path(struct Buffer *buf)
Buffer wrapper around imap_path_canon()
Definition: imap.c:2442
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:282
struct Envelope * env
Envelope information.
Definition: email.h:90
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2402
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
int mutt_file_sanitize_regex(struct Buffer *dest, const char *src)
Escape any regex-magic characters in a string.
Definition: file.c:637
#define PATH_MAX
Definition: mutt.h:40
char * data
Pointer to data.
Definition: buffer.h:35
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
WHERE char * LastFolder
Previously selected mailbox.
Definition: mutt_globals.h:51
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1317
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:50
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
#define TAILQ_EMPTY(head)
Definition: queue.h:721
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
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:265
+ 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 603 of file muttlib.c.

604 {
605  if (!buf || !buf->data)
606  return;
607  /* This reduces the size of the Buffer, so we can pass it through.
608  * We adjust the size just to make sure buf->data is not NULL though */
610  mutt_pretty_mailbox(buf->data, buf->dsize);
612 }
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:526
size_t dsize
Length of data.
Definition: buffer.h:37
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
#define PATH_MAX
Definition: mutt.h:40
char * data
Pointer to data.
Definition: buffer.h:35
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:265
+ 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 1657 of file muttlib.c.

1658 {
1659  if (!buf || !path)
1660  return;
1661 
1662  mutt_buffer_reset(buf);
1663 
1664  for (; *path; path++)
1665  {
1666  if ((slash && (*path == '/')) || !strchr(filename_safe_chars, *path))
1667  mutt_buffer_addch(buf, '_');
1668  else
1669  mutt_buffer_addch(buf, *path);
1670  }
1671 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
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_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 733 of file muttlib.c.

734 {
735  if (a && a->mailbox)
736  {
737  mutt_buffer_strcpy(dest, a->mailbox);
738  const bool c_save_address = cs_subset_bool(NeoMutt->sub, "save_address");
739  if (!c_save_address)
740  {
741  char *p = strpbrk(dest->data, "%@");
742  if (p)
743  {
744  *p = '\0';
745  mutt_buffer_fix_dptr(dest);
746  }
747  }
748  mutt_str_lower(dest->data);
749  }
750  else
751  mutt_buffer_reset(dest);
752 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
char * mailbox
Mailbox and host address.
Definition: address.h:38
Container for Accounts, Notifications.
Definition: neomutt.h:36
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
char * data
Pointer to data.
Definition: buffer.h:35
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
Definition: string.c:504
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_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 625 of file muttlib.c.

627 {
628  struct stat st;
629 
630  mutt_buffer_strcpy(fname, path);
631  if (access(mutt_buffer_string(fname), F_OK) != 0)
632  return 0;
633  if (stat(mutt_buffer_string(fname), &st) != 0)
634  return -1;
635  if (S_ISDIR(st.st_mode))
636  {
637  enum QuadOption ans = MUTT_NO;
638  if (directory)
639  {
640  switch (mutt_multi_choice
641  /* L10N: Means "The path you specified as the destination file is a directory."
642  See the msgid "Save to file: " (alias.c, recvattach.c)
643  These three letters correspond to the choices in the string. */
644  (_("File is a directory, save under it: (y)es, (n)o, (a)ll?"), _("yna")))
645  {
646  case 3: /* all */
647  mutt_str_replace(directory, mutt_buffer_string(fname));
648  break;
649  case 1: /* yes */
650  FREE(directory);
651  break;
652  case -1: /* abort */
653  FREE(directory);
654  return -1;
655  case 2: /* no */
656  FREE(directory);
657  return 1;
658  }
659  }
660  /* L10N: Means "The path you specified as the destination file is a directory."
661  See the msgid "Save to file: " (alias.c, recvattach.c) */
662  else if ((ans = mutt_yesorno(_("File is a directory, save under it?"), MUTT_YES)) != MUTT_YES)
663  return (ans == MUTT_NO) ? 1 : -1;
664 
665  struct Buffer *tmp = mutt_buffer_pool_get();
667  if ((mutt_buffer_get_field(_("File under directory: "), tmp, MUTT_FILE | MUTT_CLEAR,
668  false, NULL, NULL, NULL) != 0) ||
670  {
672  return (-1);
673  }
674  mutt_buffer_concat_path(fname, path, mutt_buffer_string(tmp));
676  }
677 
678  if ((*opt == MUTT_SAVE_NO_FLAGS) && (access(mutt_buffer_string(fname), F_OK) == 0))
679  {
680  switch (
681  mutt_multi_choice(_("File exists, (o)verwrite, (a)ppend, or (c)ancel?"),
682  // L10N: Options for: File exists, (o)verwrite, (a)ppend, or (c)ancel?
683  _("oac")))
684  {
685  case -1: /* abort */
686  return -1;
687  case 3: /* cancel */
688  return 1;
689 
690  case 2: /* append */
691  *opt = MUTT_SAVE_APPEND;
692  break;
693  case 1: /* overwrite */
694  *opt = MUTT_SAVE_OVERWRITE;
695  break;
696  }
697  }
698  return 0;
699 }
#define NONULL(x)
Definition: string2.h:37
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:58
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
const char * mutt_path_basename(const char *f)
Find the last component for a pathname.
Definition: path.c:329
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: curs_lib.c:268
No flags set.
Definition: mutt_attach.h:57
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
Overwrite existing file.
Definition: mutt_attach.h:59
#define _(a)
Definition: message.h:28
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: question.c:49
#define MUTT_FILE
Do file completion.
Definition: mutt.h:54
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:180
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
Append to existing file.
Definition: mutt_attach.h:58
#define FREE(x)
Definition: memory.h:40
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:374
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.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 1490 of file muttlib.c.

1491 {
1492  char *p = mutt_str_dup(src);
1493  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
1494  int rc = mutt_ch_convert_string(&p, c_charset, "us-ascii", MUTT_ICONV_NO_FLAGS);
1495  size_t len = mutt_buffer_strcpy(buf, (rc == 0) ? NONULL(p) : NONULL(src));
1496 
1497  /* convert the path to POSIX "Portable Filename Character Set" */
1498  for (size_t i = 0; i < len; i++)
1499  {
1500  if (!isalnum(buf->data[i]) && !strchr("/.-_", buf->data[i]))
1501  {
1502  buf->data[i] = '_';
1503  }
1504  }
1505  FREE(&p);
1506 }
#define NONULL(x)
Definition: string2.h:37
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:758
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
Container for Accounts, Notifications.
Definition: neomutt.h:36
char * data
Pointer to data.
Definition: buffer.h:35
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
#define FREE(x)
Definition: memory.h:40
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 122 of file muttlib.c.

123 {
124  return mutt_expand_path_regex(buf, buflen, false);
125 }
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_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));
341  mutt_buffer_expand_path_regex(tmp, regex);
342  mutt_str_copy(buf, mutt_buffer_string(tmp), buflen);
343 
345 
346  return buf;
347 }
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
void mutt_buffer_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:134
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
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:749
+ 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 =
373  cs_subset_regex(NeoMutt->sub, "gecos_mask");
374  if (mutt_regex_capture(c_gecos_mask, pw->pw_gecos, 1, pat_match))
375  {
376  mutt_str_copy(dest, pw->pw_gecos + pat_match[0].rm_so,
377  MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
378  }
379  else if ((p = strchr(pw->pw_gecos, ',')))
380  mutt_str_copy(dest, pw->pw_gecos, MIN(destlen, p - pw->pw_gecos + 1));
381  else
382  mutt_str_copy(dest, pw->pw_gecos, destlen);
383 
384  pwnl = strlen(pw->pw_name);
385 
386  for (int idx = 0; dest[idx]; idx++)
387  {
388  if (dest[idx] == '&')
389  {
390  memmove(&dest[idx + pwnl], &dest[idx + 1],
391  MAX((ssize_t) (destlen - idx - pwnl - 1), 0));
392  memcpy(&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl));
393  dest[idx] = toupper((unsigned char) dest[idx]);
394  }
395  }
396 
397  return dest;
398 }
#define MIN(a, b)
Definition: memory.h:31
size_t idx
Definition: mailbox.c:257
Container for Accounts, Notifications.
Definition: neomutt.h:36
#define MAX(a, b)
Definition: memory.h:30
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:243
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:596
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:749
Cached regular expression.
Definition: regex3.h:89
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_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 1555 of file muttlib.c.

1556 {
1557  enum MailboxType mb_type = mx_path_probe(path);
1558 
1559  const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
1560  if (mb_type == MUTT_IMAP)
1561  imap_get_parent_path(path, buf, buflen);
1562  else if (mb_type == MUTT_NOTMUCH)
1563  mutt_str_copy(buf, c_folder, buflen);
1564  else
1565  {
1566  mutt_str_copy(buf, path, buflen);
1567  int n = mutt_str_len(buf);
1568  if (n == 0)
1569  return;
1570 
1571  /* remove any final trailing '/' */
1572  if (buf[n - 1] == '/')
1573  buf[n - 1] = '\0';
1574 
1575  /* Remove everything until the next slash */
1576  for (n--; ((n >= 0) && (buf[n] != '/')); n--)
1577  ; // do nothing
1578 
1579  if (n > 0)
1580  buf[n] = '\0';
1581  else
1582  {
1583  buf[0] = '/';
1584  buf[1] = '\0';
1585  }
1586  }
1587 }
Container for Accounts, Notifications.
Definition: neomutt.h:36
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
Definition: util.c:161
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1317
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
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:749
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
+ 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 1611 of file muttlib.c.

1612 {
1613  /* fast-track in case the paths have been mutt_pretty_mailbox'ified */
1614  if ((a[0] == '+') && (b[0] == '+'))
1615  {
1616  return mutt_istr_equal(a + 1, "inbox") ? -1 :
1617  mutt_istr_equal(b + 1, "inbox") ? 1 :
1618  0;
1619  }
1620 
1621  const char *a_end = strrchr(a, '/');
1622  const char *b_end = strrchr(b, '/');
1623 
1624  /* If one path contains a '/', but not the other */
1625  if ((!a_end) ^ (!b_end))
1626  return 0;
1627 
1628  /* If neither path contains a '/' */
1629  if (!a_end)
1630  return 0;
1631 
1632  /* Compare the subpaths */
1633  size_t a_len = a_end - a;
1634  size_t b_len = b_end - b;
1635  size_t min = MIN(a_len, b_len);
1636  int same = (a[min] == '/') && (b[min] == '/') && (a[min + 1] != '\0') &&
1637  (b[min + 1] != '\0') && mutt_istrn_equal(a, b, min);
1638 
1639  if (!same)
1640  return 0;
1641 
1642  if (mutt_istr_equal(&a[min + 1], "inbox"))
1643  return -1;
1644 
1645  if (mutt_istr_equal(&b[min + 1], "inbox"))
1646  return 1;
1647 
1648  return 0;
1649 }
#define MIN(a, b)
Definition: memory.h:31
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:621
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
+ 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 434 of file muttlib.c.

435 {
436  int t = b->type;
437  char *s = b->subtype;
438 
440  return false;
441 
442  if (t == TYPE_TEXT)
443  return true;
444 
445  if (t == TYPE_MESSAGE)
446  {
447  if (mutt_istr_equal("delivery-status", s))
448  return true;
449  }
450 
451  if (((WithCrypto & APPLICATION_PGP) != 0) && (t == TYPE_APPLICATION))
452  {
453  if (mutt_istr_equal("pgp-keys", s))
454  return true;
455  }
456 
457  return false;
458 }
#define WithCrypto
Definition: lib.h:113
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
char * subtype
content-type subtype
Definition: body.h:37
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
Type: &#39;text/*&#39;.
Definition: mime.h:38
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;message/*&#39;.
Definition: mime.h:35
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:565
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ 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 1476 of file muttlib.c.

1477 {
1478  static char vstring[256];
1479  snprintf(vstring, sizeof(vstring), "NeoMutt %s%s", PACKAGE_VERSION, GitVer);
1480  return vstring;
1481 }
const char * GitVer

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

498 {
499  const char *const c_tmpdir = cs_subset_path(NeoMutt->sub, "tmpdir");
500  size_t n =
501  snprintf(buf, buflen, "%s/%s-%s-%d-%d-%" PRIu64 "%s%s", NONULL(c_tmpdir),
502  NONULL(prefix), NONULL(ShortHostname), (int) getuid(),
503  (int) getpid(), mutt_rand64(), suffix ? "." : "", NONULL(suffix));
504  if (n >= buflen)
505  {
507  "%s:%d: ERROR: insufficient buffer space to hold temporary "
508  "filename! buflen=%zu but need %zu\n",
509  src, line, buflen, n);
510  }
511  mutt_debug(LL_DEBUG3, "%s:%d: mutt_mktemp returns \"%s\"\n", src, line, buf);
512  if ((unlink(buf) != 0) && (errno != ENOENT))
513  {
514  mutt_debug(LL_DEBUG1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src,
515  line, buf, strerror(errno), errno);
516  }
517 }
#define NONULL(x)
Definition: string2.h:37
Container for Accounts, Notifications.
Definition: neomutt.h:36
uint64_t mutt_rand64(void)
Create a 64-bit random number.
Definition: random.c:130
WHERE char * ShortHostname
Short version of the hostname.
Definition: mutt_globals.h:46
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Log at debug level 3.
Definition: logging.h:42
+ Here is the call 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 406 of file muttlib.c.

407 {
408  switch (m->type)
409  {
410  case TYPE_TEXT:
411  if (mutt_istr_equal("plain", m->subtype))
412  return false;
413  break;
414  case TYPE_APPLICATION:
416  return false;
418  return false;
419  break;
420 
421  case TYPE_MULTIPART:
422  case TYPE_MESSAGE:
423  return false;
424  }
425 
426  return true;
427 }
#define WithCrypto
Definition: lib.h:113
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:623
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
char * subtype
content-type subtype
Definition: body.h:37
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
Type: &#39;text/*&#39;.
Definition: mime.h:38
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;message/*&#39;.
Definition: mime.h:35
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:565
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ 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 1315 of file muttlib.c.

1316 {
1317  FILE *fp = NULL;
1318  struct stat s;
1319 
1320  size_t len = mutt_str_len(path);
1321  if (len == 0)
1322  {
1323  return NULL;
1324  }
1325 
1326  if (path[len - 1] == '|')
1327  {
1328  /* read from a pipe */
1329 
1330  char *p = mutt_str_dup(path);
1331 
1332  p[len - 1] = 0;
1333  mutt_endwin();
1334  *thepid = filter_create(p, NULL, &fp, NULL);
1335  FREE(&p);
1336  }
1337  else
1338  {
1339  if (stat(path, &s) < 0)
1340  return NULL;
1341  if (S_ISDIR(s.st_mode))
1342  {
1343  errno = EINVAL;
1344  return NULL;
1345  }
1346  fp = fopen(path, "r");
1347  *thepid = -1;
1348  }
1349  return fp;
1350 }
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:370
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:422
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
#define FREE(x)
Definition: memory.h:40
+ 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 526 of file muttlib.c.

527 {
528  if (!buf)
529  return;
530 
531  char *p = buf, *q = buf;
532  size_t len;
533  enum UrlScheme scheme;
534  char tmp[PATH_MAX];
535 
536  scheme = url_check_scheme(buf);
537 
538  const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
539  if ((scheme == U_IMAP) || (scheme == U_IMAPS))
540  {
541  imap_pretty_mailbox(buf, buflen, c_folder);
542  return;
543  }
544 
545  if (scheme == U_NOTMUCH)
546  return;
547 
548  /* if buf is an url, only collapse path component */
549  if (scheme != U_UNKNOWN)
550  {
551  p = strchr(buf, ':') + 1;
552  if (mutt_strn_equal(p, "//", 2))
553  q = strchr(p + 2, '/');
554  if (!q)
555  q = strchr(p, '\0');
556  p = q;
557  }
558 
559  /* cleanup path */
560  if (strstr(p, "//") || strstr(p, "/./"))
561  {
562  /* first attempt to collapse the pathname, this is more
563  * lightweight than realpath() and doesn't resolve links */
564  while (*p)
565  {
566  if ((p[0] == '/') && (p[1] == '/'))
567  {
568  *q++ = '/';
569  p += 2;
570  }
571  else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
572  {
573  *q++ = '/';
574  p += 3;
575  }
576  else
577  *q++ = *p++;
578  }
579  *q = '\0';
580  }
581  else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
582  realpath(p, tmp))
583  {
584  mutt_str_copy(p, tmp, buflen - (p - buf));
585  }
586 
587  if ((len = mutt_str_startswith(buf, c_folder)) && (buf[len] == '/'))
588  {
589  *buf++ = '=';
590  memmove(buf, buf + len, mutt_str_len(buf + len) + 1);
591  }
592  else if ((len = mutt_str_startswith(buf, HomeDir)) && (buf[len] == '/'))
593  {
594  *buf++ = '~';
595  memmove(buf, buf + len - 1, mutt_str_len(buf + len - 1) + 1);
596  }
597 }
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition: url.c:221
Url is notmuch://.
Definition: url.h:46
Url is imaps://.
Definition: url.h:40
Url wasn&#39;t recognised.
Definition: url.h:35
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:590
Url is imap://.
Definition: url.h:39
Container for Accounts, Notifications.
Definition: neomutt.h:36
char * HomeDir
User&#39;s home directory.
Definition: mutt_globals.h:45
UrlScheme
All recognised Url types.
Definition: url.h:33
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
#define PATH_MAX
Definition: mutt.h:40
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
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:749
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:593
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Url is file://.
Definition: url.h:36
+ 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 761 of file muttlib.c.

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

1361 {
1362  int ret = 0;
1363 
1364  enum MailboxType type = mx_path_probe(s);
1365 
1366 #ifdef USE_POP
1367  if (type == MUTT_POP)
1368  {
1369  mutt_error(_("Can't save message to POP mailbox"));
1370  return 1;
1371  }
1372 #endif
1373 
1374  if ((type != MUTT_MAILBOX_ERROR) && (type != MUTT_UNKNOWN) && (mx_access(s, W_OK) == 0))
1375  {
1376  const bool c_confirm_append =
1377  cs_subset_bool(NeoMutt->sub, "confirm_append");
1378  if (c_confirm_append)
1379  {
1380  struct Buffer *tmp = mutt_buffer_pool_get();
1381  mutt_buffer_printf(tmp, _("Append messages to %s?"), s);
1383  if (ans == MUTT_NO)
1384  ret = 1;
1385  else if (ans == MUTT_ABORT)
1386  ret = -1;
1388  }
1389  }
1390 
1391 #ifdef USE_NNTP
1392  if (type == MUTT_NNTP)
1393  {
1394  mutt_error(_("Can't save message to news server"));
1395  return 0;
1396  }
1397 #endif
1398 
1399  if (stat(s, st) != -1)
1400  {
1401  if (type == MUTT_MAILBOX_ERROR)
1402  {
1403  mutt_error(_("%s is not a mailbox"), s);
1404  return 1;
1405  }
1406  }
1407  else if (type != MUTT_IMAP)
1408  {
1409  st->st_mtime = 0;
1410  st->st_atime = 0;
1411 
1412  /* pathname does not exist */
1413  if (errno == ENOENT)
1414  {
1415  const bool c_confirm_create =
1416  cs_subset_bool(NeoMutt->sub, "confirm_create");
1417  if (c_confirm_create)
1418  {
1419  struct Buffer *tmp = mutt_buffer_pool_get();
1420  mutt_buffer_printf(tmp, _("Create %s?"), s);
1422  if (ans == MUTT_NO)
1423  ret = 1;
1424  else if (ans == MUTT_ABORT)
1425  ret = -1;
1427  }
1428 
1429  /* user confirmed with MUTT_YES or set `$confirm_create` */
1430  if (ret == 0)
1431  {
1432  /* create dir recursively */
1433  char *tmp_path = mutt_path_dirname(s);
1434  if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
1435  {
1436  /* report failure & abort */
1437  mutt_perror(s);
1438  FREE(&tmp_path);
1439  return 1;
1440  }
1441  FREE(&tmp_path);
1442  }
1443  }
1444  else
1445  {
1446  mutt_perror(s);
1447  return 1;
1448  }
1449  }
1450 
1452  return ret;
1453 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:52
#define mutt_error(...)
Definition: logging.h:88
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final &#39;/&#39;.
Definition: path.c:376
#define _(a)
Definition: message.h:28
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:47
Error occurred examining Mailbox.
Definition: mailbox.h:46
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
void msgwin_clear_text(void)
Clear the text in the Message Window.
Definition: msgwin.c:242
#define mutt_perror(...)
Definition: logging.h:89
Container for Accounts, Notifications.
Definition: neomutt.h:36
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:877
User aborted the question (with Ctrl-G)
Definition: quad.h:37
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:55
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:180
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1317
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
#define FREE(x)
Definition: memory.h:40
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
Definition: mx.c:184
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
+ 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 710 of file muttlib.c.

711 {
712  if (addr && addr->mailbox)
713  {
714  mutt_str_copy(buf, addr->mailbox, buflen);
715  const bool c_save_address = cs_subset_bool(NeoMutt->sub, "save_address");
716  if (!c_save_address)
717  {
718  char *p = strpbrk(buf, "%@");
719  if (p)
720  *p = '\0';
721  }
722  mutt_str_lower(buf);
723  }
724  else
725  *buf = '\0';
726 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
char * mailbox
Mailbox and host address.
Definition: address.h:38
Container for Accounts, Notifications.
Definition: neomutt.h:36
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:749
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
Definition: string.c:504
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_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 1461 of file muttlib.c.

1462 {
1463  const short c_sleep_time = cs_subset_number(NeoMutt->sub, "sleep_time");
1464  if (c_sleep_time > s)
1465  sleep(c_sleep_time);
1466  else if (s)
1467  sleep(s);
1468 }
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
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_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 1679 of file muttlib.c.

1680 {
1681  if (!buf || (buflen == 0))
1682  return;
1683 
1684  const bool c_size_show_bytes =
1685  cs_subset_bool(NeoMutt->sub, "size_show_bytes");
1686  const bool c_size_show_fractions =
1687  cs_subset_bool(NeoMutt->sub, "size_show_fractions");
1688  const bool c_size_show_mb = cs_subset_bool(NeoMutt->sub, "size_show_mb");
1689  const bool c_size_units_on_left =
1690  cs_subset_bool(NeoMutt->sub, "size_units_on_left");
1691 
1692  if (c_size_show_bytes && (num < 1024))
1693  {
1694  snprintf(buf, buflen, "%d", (int) num);
1695  }
1696  else if (num == 0)
1697  {
1698  mutt_str_copy(buf, c_size_units_on_left ? "K0" : "0K", buflen);
1699  }
1700  else if (c_size_show_fractions && (num < 10189)) /* 0.1K - 9.9K */
1701  {
1702  snprintf(buf, buflen, c_size_units_on_left ? "K%3.1f" : "%3.1fK",
1703  (num < 103) ? 0.1 : (num / 1024.0));
1704  }
1705  else if (!c_size_show_mb || (num < 1023949)) /* 10K - 999K */
1706  {
1707  /* 51 is magic which causes 10189/10240 to be rounded up to 10 */
1708  snprintf(buf, buflen, c_size_units_on_left ? ("K%zu") : ("%zuK"), (num + 51) / 1024);
1709  }
1710  else if (c_size_show_fractions && (num < 10433332)) /* 1.0M - 9.9M */
1711  {
1712  snprintf(buf, buflen, c_size_units_on_left ? "M%3.1f" : "%3.1fM", num / 1048576.0);
1713  }
1714  else /* 10M+ */
1715  {
1716  /* (10433332 + 52428) / 1048576 = 10 */
1717  snprintf(buf, buflen, c_size_units_on_left ? ("M%zu") : ("%zuM"), (num + 52428) / 1048576);
1718  }
1719 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Container for Accounts, Notifications.
Definition: neomutt.h:36
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:749
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:

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

1729 {
1730  /* don't add a NULL or empty string to the list */
1731  if (!str || (*str == '\0'))
1732  return;
1733 
1734  /* check to make sure the item is not already on this list */
1735  struct ListNode *np = NULL;
1736  STAILQ_FOREACH(np, head, entries)
1737  {
1738  if (mutt_istr_equal(str, np->data))
1739  {
1740  return;
1741  }
1742  }
1743  mutt_list_insert_tail(head, mutt_str_dup(str));
1744 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
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
char * data
String.
Definition: list.h:36
A List node for strings.
Definition: list.h:34
+ 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 1753 of file muttlib.c.

1754 {
1755  if (mutt_str_equal("*", str))
1756  mutt_list_free(head); /* "unCMD *" means delete all current entries */
1757  else
1758  {
1759  struct ListNode *np = NULL, *tmp = NULL;
1760  STAILQ_FOREACH_SAFE(np, head, entries, tmp)
1761  {
1762  if (mutt_istr_equal(str, np->data))
1763  {
1764  STAILQ_REMOVE(head, np, ListNode, entries);
1765  FREE(&np->data);
1766  FREE(&np);
1767  break;
1768  }
1769  }
1770  }
1771 }
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:402
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
char * data
String.
Definition: list.h:36
#define FREE(x)
Definition: memory.h:40
A List node for strings.
Definition: list.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function: