NeoMutt  2019-12-07
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_encode_path (struct Buffer *buf, const char *src)
 Convert a path into the user's preferred character set. 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 (char *dest, size_t dlen, const char *src)
 Convert a path into the user's preferred character set. More...
 
void mutt_expando_format (char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long 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...
 
uint32_t mutt_rand32 (void)
 Create a 32-bit random number. More...
 
uint64_t mutt_rand64 (void)
 Create a 64-bit random number. More...
 
void mutt_rand_base32 (void *out, size_t len)
 Fill a buffer with a base32-encoded random string. More...
 
int mutt_randbuf (void *out, size_t len)
 Fill a buffer with randomness. 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...
 

Variables

struct RegexC_GecosMask
 Config: Regex for parsing GECOS field of /etc/passwd. 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 75 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 76 of file muttlib.h.

◆ mutt_buffer_mktemp

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

Definition at line 78 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 79 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 96 of file muttlib.c.

97 {
98  if (!(buf->data && buf->data[0]))
99  {
100  mutt_buffer_mktemp(buf);
101  }
102  else
103  {
104  struct Buffer *prefix = mutt_buffer_pool_get();
105  mutt_buffer_strcpy(prefix, buf->data);
106  mutt_file_sanitize_filename(prefix->data, true);
107  mutt_buffer_printf(buf, "%s/%s", NONULL(C_Tmpdir), mutt_b2s(prefix));
108 
109  struct stat sb;
110  if ((lstat(mutt_b2s(buf), &sb) == -1) && (errno == ENOENT))
111  goto out;
112 
113  char *suffix = strchr(prefix->data, '.');
114  if (suffix)
115  {
116  *suffix = '\0';
117  suffix++;
118  }
119  mutt_buffer_mktemp_pfx_sfx(buf, prefix->data, suffix);
120 
121  out:
122  mutt_buffer_pool_release(&prefix);
123  }
124 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:78
#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:79
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
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:615
#define mutt_b2s(buf)
Definition: buffer.h:41
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 * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:55
+ 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 573 of file muttlib.c.

575 {
576  mutt_buffer_printf(buf, "%s/%s-%s-%d-%d-%" PRIu64 "%s%s", NONULL(C_Tmpdir),
577  NONULL(prefix), NONULL(ShortHostname), (int) getuid(),
578  (int) getpid(), mutt_rand64(), suffix ? "." : "", NONULL(suffix));
579 
580  mutt_debug(LL_DEBUG3, "%s:%d: mutt_mktemp returns \"%s\"\n", src, line, mutt_b2s(buf));
581  if (unlink(mutt_b2s(buf)) && (errno != ENOENT))
582  {
583  mutt_debug(LL_DEBUG1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src,
584  line, mutt_b2s(buf), strerror(errno), errno);
585  }
586 }
#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
#define mutt_b2s(buf)
Definition: buffer.h:41
const char * line
Definition: common.c:36
uint64_t mutt_rand64(void)
Create a 64-bit random number.
Definition: muttlib.c:556
Log at debug level 1.
Definition: logging.h:40
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:55
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:51
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Log at debug level 3.
Definition: logging.h:42
+ Here is the call graph for this function:

◆ mutt_buffer_encode_path()

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

Convert a path into the user's preferred character set.

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

1601 {
1602  char *p = mutt_str_strdup(src);
1603  int rc = mutt_ch_convert_string(&p, C_Charset, "utf-8", 0);
1604  mutt_buffer_strcpy(buf, (rc == 0) ? NONULL(p) : NONULL(src));
1605  FREE(&p);
1606 }
#define NONULL(x)
Definition: string2.h:37
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:748
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_expand_path()

void mutt_buffer_expand_path ( struct Buffer buf)

Create the canonical path.

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

Definition at line 343 of file muttlib.c.

344 {
345  mutt_buffer_expand_path_regex(buf, false);
346 }
void mutt_buffer_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:146
+ 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 146 of file muttlib.c.

147 {
148  const char *s = NULL;
149  const char *tail = "";
150 
151  bool recurse = false;
152 
153  struct Buffer *p = mutt_buffer_pool_get();
154  struct Buffer *q = mutt_buffer_pool_get();
155  struct Buffer *tmp = mutt_buffer_pool_get();
156 
157  do
158  {
159  recurse = false;
160  s = mutt_b2s(buf);
161 
162  switch (*s)
163  {
164  case '~':
165  {
166  if ((s[1] == '/') || (s[1] == '\0'))
167  {
169  tail = s + 1;
170  }
171  else
172  {
173  char *t = strchr(s + 1, '/');
174  if (t)
175  *t = '\0';
176 
177  struct passwd *pw = getpwnam(s + 1);
178  if (pw)
179  {
180  mutt_buffer_strcpy(p, pw->pw_dir);
181  if (t)
182  {
183  *t = '/';
184  tail = t;
185  }
186  else
187  tail = "";
188  }
189  else
190  {
191  /* user not found! */
192  if (t)
193  *t = '/';
195  tail = s;
196  }
197  }
198  break;
199  }
200 
201  case '=':
202  case '+':
203  {
204  enum MailboxType mb_type = mx_path_probe(C_Folder, NULL);
205 
206  /* if folder = {host} or imap[s]://host/: don't append slash */
207  if ((mb_type == MUTT_IMAP) && ((C_Folder[strlen(C_Folder) - 1] == '}') ||
208  (C_Folder[strlen(C_Folder) - 1] == '/')))
209  {
211  }
212  else if (mb_type == MUTT_NOTMUCH)
214  else if (C_Folder && (C_Folder[strlen(C_Folder) - 1] == '/'))
216  else
217  mutt_buffer_printf(p, "%s/", NONULL(C_Folder));
218 
219  tail = s + 1;
220  break;
221  }
222 
223  /* elm compatibility, @ expands alias to user name */
224 
225  case '@':
226  {
227  struct AddressList *al = mutt_alias_lookup(s + 1);
228  if (!TAILQ_EMPTY(al))
229  {
230  struct Email *e = email_new();
231  e->env = mutt_env_new();
232  mutt_addrlist_copy(&e->env->from, al, false);
233  mutt_addrlist_copy(&e->env->to, al, false);
234 
235  /* TODO: fix mutt_default_save() to use Buffer */
237  mutt_default_save(p->data, p->dsize, e);
239 
240  email_free(&e);
241  /* Avoid infinite recursion if the resulting folder starts with '@' */
242  if (*p->data != '@')
243  recurse = true;
244 
245  tail = "";
246  }
247  break;
248  }
249 
250  case '>':
251  {
253  tail = s + 1;
254  break;
255  }
256 
257  case '<':
258  {
260  tail = s + 1;
261  break;
262  }
263 
264  case '!':
265  {
266  if (s[1] == '!')
267  {
269  tail = s + 2;
270  }
271  else
272  {
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  {
296  tail = s;
297  }
298  }
299 
300  if (regex && *(mutt_b2s(p)) && !recurse)
301  {
303  mutt_buffer_printf(tmp, "%s%s", mutt_b2s(q), tail);
304  }
305  else
306  mutt_buffer_printf(tmp, "%s%s", mutt_b2s(p), tail);
307 
308  mutt_buffer_copy(buf, tmp);
309  } while (recurse);
310 
314 
315 #ifdef USE_IMAP
316  /* Rewrite IMAP path in canonical form - aids in string comparisons of
317  * folders. May possibly fail, in which case buf should be the same. */
318  if (imap_path_probe(mutt_b2s(buf), NULL) == MUTT_IMAP)
319  imap_expand_path(buf);
320  else
321 #endif
322  {
323  /* Resolve symbolic links */
324  struct stat st;
325  int rc = lstat(mutt_b2s(buf), &st);
326  if ((rc != -1) && S_ISLNK(st.st_mode))
327  {
328  char path[PATH_MAX];
329  if (realpath(mutt_b2s(buf), path))
330  {
331  mutt_buffer_strcpy(buf, path);
332  }
333  }
334  }
335 }
#define NONULL(x)
Definition: string2.h:37
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct AddressList * mutt_alias_lookup(const char *s)
Find an Alias.
Definition: alias.c:285
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
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2474
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:727
String manipulation buffer.
Definition: buffer.h:33
WHERE char * LastFolder
Previously selected mailbox.
Definition: globals.h:56
WHERE char * C_Record
Config: Folder to save &#39;sent&#39; messages.
Definition: globals.h:132
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:656
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:2520
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
WHERE char * C_Mbox
Config: Folder that receives read emails (see Move)
Definition: globals.h:118
struct Envelope * env
Envelope information.
Definition: email.h:89
WHERE char * HomeDir
User&#39;s home directory.
Definition: globals.h:50
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: globals.h:55
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
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:634
#define mutt_b2s(buf)
Definition: buffer.h:41
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:120
#define PATH_MAX
Definition: mutt.h:50
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
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:53
MailboxType
Supported mailbox formats.
Definition: mailbox.h:42
WHERE char * C_Spoolfile
Config: Inbox.
Definition: globals.h:145
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
struct Email * email_new(void)
Create a new Email.
Definition: email.c:68
#define TAILQ_EMPTY(head)
Definition: queue.h:715
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:41
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1290
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
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 704 of file muttlib.c.

705 {
706  if (!buf || !buf->data)
707  return;
708  /* This reduces the size of the Buffer, so we can pass it through.
709  * We adjust the size just to make sure buf->data is not NULL though */
711  mutt_pretty_mailbox(buf->data, buf->dsize);
713 }
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:628
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:50
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 1757 of file muttlib.c.

1758 {
1759  if (!buf || !path)
1760  return;
1761 
1762  mutt_buffer_reset(buf);
1763 
1764  for (; *path; path++)
1765  {
1766  if ((slash && (*path == '/')) || !strchr(filename_safe_chars, *path))
1767  mutt_buffer_addch(buf, '_');
1768  else
1769  mutt_buffer_addch(buf, *path);
1770  }
1771 }
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
const char filename_safe_chars[]
Definition: file.c:60
+ 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 832 of file muttlib.c.

833 {
834  if (a && a->mailbox)
835  {
836  mutt_buffer_strcpy(dest, a->mailbox);
837  if (!C_SaveAddress)
838  {
839  char *p = strpbrk(dest->data, "%@");
840  if (p)
841  {
842  *p = '\0';
843  mutt_buffer_fix_dptr(dest);
844  }
845  }
846  mutt_str_strlower(dest->data);
847  }
848  else
849  mutt_buffer_reset(dest);
850 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
char * mailbox
Mailbox and host address.
Definition: address.h:37
char * mutt_str_strlower(char *s)
convert all characters in the string to lowercase
Definition: string.c:509
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
WHERE bool C_SaveAddress
Config: Use sender&#39;s full address as a default save folder.
Definition: globals.h:252
+ 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 726 of file muttlib.c.

728 {
729  struct stat st;
730 
731  mutt_buffer_strcpy(fname, path);
732  if (access(mutt_b2s(fname), F_OK) != 0)
733  return 0;
734  if (stat(mutt_b2s(fname), &st) != 0)
735  return -1;
736  if (S_ISDIR(st.st_mode))
737  {
738  enum QuadOption ans = MUTT_NO;
739  if (directory)
740  {
741  switch (mutt_multi_choice
742  /* L10N: Means "The path you specified as the destination file is a directory."
743  See the msgid "Save to file: " (alias.c, recvattach.c)
744  These three letters correspond to the choices in the string. */
745  (_("File is a directory, save under it: (y)es, (n)o, (a)ll?"), _("yna")))
746  {
747  case 3: /* all */
748  mutt_str_replace(directory, mutt_b2s(fname));
749  break;
750  case 1: /* yes */
751  FREE(directory);
752  break;
753  case -1: /* abort */
754  FREE(directory);
755  return -1;
756  case 2: /* no */
757  FREE(directory);
758  return 1;
759  }
760  }
761  /* L10N: Means "The path you specified as the destination file is a directory."
762  See the msgid "Save to file: " (alias.c, recvattach.c) */
763  else if ((ans = mutt_yesorno(_("File is a directory, save under it?"), MUTT_YES)) != MUTT_YES)
764  return (ans == MUTT_NO) ? 1 : -1;
765 
766  struct Buffer *tmp = mutt_buffer_pool_get();
768  if ((mutt_buffer_get_field(_("File under directory: "), tmp, MUTT_FILE | MUTT_CLEAR) != 0) ||
770  {
772  return (-1);
773  }
774  mutt_buffer_concat_path(fname, path, mutt_b2s(tmp));
776  }
777 
778  if ((*opt == MUTT_SAVE_NO_FLAGS) && (access(mutt_b2s(fname), F_OK) == 0))
779  {
780  switch (
781  mutt_multi_choice(_("File exists, (o)verwrite, (a)ppend, or (c)ancel?"),
782  // L10N: Options for: File exists, (o)verwrite, (a)ppend, or (c)ancel?
783  _("oac")))
784  {
785  case -1: /* abort */
786  return -1;
787  case 3: /* cancel */
788  return 1;
789 
790  case 2: /* append */
791  *opt = MUTT_SAVE_APPEND;
792  break;
793  case 1: /* overwrite */
794  *opt = MUTT_SAVE_OVERWRITE;
795  break;
796  }
797  }
798  return 0;
799 }
#define NONULL(x)
Definition: string2.h:37
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:68
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
No flags set.
Definition: mutt_attach.h:55
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:57
#define _(a)
Definition: message.h:28
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:375
const char * mutt_path_basename(const char *f)
Find the last component for a pathname.
Definition: path.c:307
#define mutt_b2s(buf)
Definition: buffer.h:41
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:862
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
#define MUTT_FILE
Do file completion.
Definition: mutt.h:64
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
#define mutt_buffer_get_field(field, buf, complete)
Definition: curs_lib.h:84
Append to existing file.
Definition: mutt_attach.h:56
#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
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_encode_path()

void mutt_encode_path ( char *  buf,
size_t  buflen,
const char *  src 
)

Convert a path into the user's preferred character set.

Parameters
bufBuffer for the result
buflenLength of buffer
srcPath to convert (OPTIONAL)

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

Definition at line 1575 of file muttlib.c.

1576 {
1577  char *p = mutt_str_strdup(src);
1578  int rc = mutt_ch_convert_string(&p, C_Charset, "us-ascii", 0);
1579  /* 'src' may be NULL, such as when called from the pop3 driver. */
1580  size_t len = mutt_str_strfcpy(buf, (rc == 0) ? p : src, buflen);
1581 
1582  /* convert the path to POSIX "Portable Filename Character Set" */
1583  for (size_t i = 0; i < len; i++)
1584  {
1585  if (!isalnum(buf[i]) && !strchr("/.-_", buf[i]))
1586  {
1587  buf[i] = '_';
1588  }
1589  }
1590  FREE(&p);
1591 }
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:748
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_expando_format()

void mutt_expando_format ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
const char *  src,
format_t callback,
unsigned long  data,
MuttFormatFlags  flags 
)

Expand expandos (x) in a string.

Parameters
[out]bufBuffer in which to save string
[in]buflenBuffer length
[in]colStarting column
[in]colsNumber of screen columns
[in]srcPrintf-like format string
[in]callbackCallback - Implements format_t
[in]dataCallback data
[in]flagsCallback flags

Definition at line 878 of file muttlib.c.

880 {
881  char prefix[128], tmp[1024];
882  char *cp = NULL, *wptr = buf;
883  char ch;
884  char if_str[128], else_str[128];
885  size_t wlen, count, len, wid;
886  FILE *fp_filter = NULL;
887  char *recycler = NULL;
888 
889  char src2[256];
890  mutt_str_strfcpy(src2, src, mutt_str_strlen(src) + 1);
891  src = src2;
892 
893  prefix[0] = '\0';
894  buflen--; /* save room for the terminal \0 */
895  wlen = ((flags & MUTT_FORMAT_ARROWCURSOR) && C_ArrowCursor) ? 3 : 0;
896  col += wlen;
897 
898  if ((flags & MUTT_FORMAT_NOFILTER) == 0)
899  {
900  int off = -1;
901 
902  /* Do not consider filters if no pipe at end */
903  int n = mutt_str_strlen(src);
904  if ((n > 1) && (src[n - 1] == '|'))
905  {
906  /* Scan backwards for backslashes */
907  off = n;
908  while ((off > 0) && (src[off - 2] == '\\'))
909  off--;
910  }
911 
912  /* If number of backslashes is even, the pipe is real. */
913  /* n-off is the number of backslashes. */
914  if ((off > 0) && (((n - off) % 2) == 0))
915  {
916  char srccopy[1024];
917  int i = 0;
918 
919  mutt_debug(LL_DEBUG3, "fmtpipe = %s\n", src);
920 
921  strncpy(srccopy, src, n);
922  srccopy[n - 1] = '\0';
923 
924  /* prepare Buffers */
925  struct Buffer srcbuf = mutt_buffer_make(0);
926  mutt_buffer_addstr(&srcbuf, srccopy);
927  /* note: we are resetting dptr and *reading* from the buffer, so we don't
928  * want to use mutt_buffer_reset(). */
929  srcbuf.dptr = srcbuf.data;
930  struct Buffer word = mutt_buffer_make(0);
931  struct Buffer cmd = mutt_buffer_make(0);
932 
933  /* Iterate expansions across successive arguments */
934  do
935  {
936  /* Extract the command name and copy to command line */
937  mutt_debug(LL_DEBUG3, "fmtpipe +++: %s\n", srcbuf.dptr);
938  if (word.data)
939  *word.data = '\0';
940  mutt_extract_token(&word, &srcbuf, MUTT_TOKEN_NO_FLAGS);
941  mutt_debug(LL_DEBUG3, "fmtpipe %2d: %s\n", i++, word.data);
942  mutt_buffer_addch(&cmd, '\'');
943  mutt_expando_format(tmp, sizeof(tmp), 0, cols, word.data, callback,
944  data, flags | MUTT_FORMAT_NOFILTER);
945  for (char *p = tmp; p && *p; p++)
946  {
947  if (*p == '\'')
948  {
949  /* shell quoting doesn't permit escaping a single quote within
950  * single-quoted material. double-quoting instead will lead
951  * shell variable expansions, so break out of the single-quoted
952  * span, insert a double-quoted single quote, and resume. */
953  mutt_buffer_addstr(&cmd, "'\"'\"'");
954  }
955  else
956  mutt_buffer_addch(&cmd, *p);
957  }
958  mutt_buffer_addch(&cmd, '\'');
959  mutt_buffer_addch(&cmd, ' ');
960  } while (MoreArgs(&srcbuf));
961 
962  mutt_debug(LL_DEBUG3, "fmtpipe > %s\n", cmd.data);
963 
964  col -= wlen; /* reset to passed in value */
965  wptr = buf; /* reset write ptr */
966  pid_t pid = mutt_create_filter(cmd.data, NULL, &fp_filter, NULL);
967  if (pid != -1)
968  {
969  int rc;
970 
971  n = fread(buf, 1, buflen /* already decremented */, fp_filter);
972  mutt_file_fclose(&fp_filter);
973  rc = mutt_wait_filter(pid);
974  if (rc != 0)
975  mutt_debug(LL_DEBUG1, "format pipe cmd exited code %d\n", rc);
976  if (n > 0)
977  {
978  buf[n] = '\0';
979  while ((n > 0) && ((buf[n - 1] == '\n') || (buf[n - 1] == '\r')))
980  buf[--n] = '\0';
981  mutt_debug(LL_DEBUG5, "fmtpipe < %s\n", buf);
982 
983  /* If the result ends with '%', this indicates that the filter
984  * generated %-tokens that neomutt can expand. Eliminate the '%'
985  * marker and recycle the string through mutt_expando_format().
986  * To literally end with "%", use "%%". */
987  if ((n > 0) && (buf[n - 1] == '%'))
988  {
989  n--;
990  buf[n] = '\0'; /* remove '%' */
991  if ((n > 0) && (buf[n - 1] != '%'))
992  {
993  recycler = mutt_str_strdup(buf);
994  if (recycler)
995  {
996  /* buflen is decremented at the start of this function
997  * to save space for the terminal nul char. We can add
998  * it back for the recursive call since the expansion of
999  * format pipes does not try to append a nul itself. */
1000  mutt_expando_format(buf, buflen + 1, col, cols, recycler,
1001  callback, data, flags);
1002  FREE(&recycler);
1003  }
1004  }
1005  }
1006  }
1007  else
1008  {
1009  /* read error */
1010  mutt_debug(LL_DEBUG1, "error reading from fmtpipe: %s (errno=%d)\n",
1011  strerror(errno), errno);
1012  *wptr = '\0';
1013  }
1014  }
1015  else
1016  {
1017  /* Filter failed; erase write buffer */
1018  *wptr = '\0';
1019  }
1020 
1021  mutt_buffer_dealloc(&cmd);
1022  mutt_buffer_dealloc(&srcbuf);
1023  mutt_buffer_dealloc(&word);
1024  return;
1025  }
1026  }
1027 
1028  while (*src && (wlen < buflen))
1029  {
1030  if (*src == '%')
1031  {
1032  if (*++src == '%')
1033  {
1034  *wptr++ = '%';
1035  wlen++;
1036  col++;
1037  src++;
1038  continue;
1039  }
1040 
1041  if (*src == '?')
1042  {
1043  /* change original %? to new %< notation */
1044  /* %?x?y&z? to %<x?y&z> where y and z are nestable */
1045  char *p = (char *) src;
1046  *p = '<';
1047  /* skip over "x" */
1048  for (; *p && *p != '?'; p++)
1049  ;
1050  /* nothing */
1051  if (*p == '?')
1052  p++;
1053  /* fix up the "y&z" section */
1054  for (; *p && *p != '?'; p++)
1055  {
1056  /* escape '<' and '>' to work inside nested-if */
1057  if ((*p == '<') || (*p == '>'))
1058  {
1059  memmove(p + 2, p, mutt_str_strlen(p) + 1);
1060  *p++ = '\\';
1061  *p++ = '\\';
1062  }
1063  }
1064  if (*p == '?')
1065  *p = '>';
1066  }
1067 
1068  if (*src == '<')
1069  {
1070  flags |= MUTT_FORMAT_OPTIONAL;
1071  ch = *(++src); /* save the character to switch on */
1072  src++;
1073  cp = prefix;
1074  count = 0;
1075  while ((count < sizeof(prefix)) && (*src != '?'))
1076  {
1077  *cp++ = *src++;
1078  count++;
1079  }
1080  *cp = '\0';
1081  }
1082  else
1083  {
1084  flags &= ~MUTT_FORMAT_OPTIONAL;
1085 
1086  /* eat the format string */
1087  cp = prefix;
1088  count = 0;
1089  while ((count < sizeof(prefix)) && (isdigit((unsigned char) *src) || (*src == '.') ||
1090  (*src == '-') || (*src == '=')))
1091  {
1092  *cp++ = *src++;
1093  count++;
1094  }
1095  *cp = '\0';
1096 
1097  if (!*src)
1098  break; /* bad format */
1099 
1100  ch = *src++; /* save the character to switch on */
1101  }
1102 
1103  if (flags & MUTT_FORMAT_OPTIONAL)
1104  {
1105  int lrbalance;
1106 
1107  if (*src != '?')
1108  break; /* bad format */
1109  src++;
1110 
1111  /* eat the 'if' part of the string */
1112  cp = if_str;
1113  count = 0;
1114  lrbalance = 1;
1115  while ((lrbalance > 0) && (count < sizeof(if_str)) && *src)
1116  {
1117  if ((src[0] == '%') && (src[1] == '>'))
1118  {
1119  /* This is a padding expando; copy two chars and carry on */
1120  *cp++ = *src++;
1121  *cp++ = *src++;
1122  count += 2;
1123  continue;
1124  }
1125 
1126  if (*src == '\\')
1127  {
1128  src++;
1129  *cp++ = *src++;
1130  }
1131  else if ((src[0] == '%') && (src[1] == '<'))
1132  {
1133  lrbalance++;
1134  }
1135  else if (src[0] == '>')
1136  {
1137  lrbalance--;
1138  }
1139  if (lrbalance == 0)
1140  break;
1141  if ((lrbalance == 1) && (src[0] == '&'))
1142  break;
1143  *cp++ = *src++;
1144  count++;
1145  }
1146  *cp = '\0';
1147 
1148  /* eat the 'else' part of the string (optional) */
1149  if (*src == '&')
1150  src++; /* skip the & */
1151  cp = else_str;
1152  count = 0;
1153  while ((lrbalance > 0) && (count < sizeof(else_str)) && *src)
1154  {
1155  if ((src[0] == '%') && (src[1] == '>'))
1156  {
1157  /* This is a padding expando; copy two chars and carry on */
1158  *cp++ = *src++;
1159  *cp++ = *src++;
1160  count += 2;
1161  continue;
1162  }
1163 
1164  if (*src == '\\')
1165  {
1166  src++;
1167  *cp++ = *src++;
1168  }
1169  else if ((src[0] == '%') && (src[1] == '<'))
1170  {
1171  lrbalance++;
1172  }
1173  else if (src[0] == '>')
1174  {
1175  lrbalance--;
1176  }
1177  if (lrbalance == 0)
1178  break;
1179  if ((lrbalance == 1) && (src[0] == '&'))
1180  break;
1181  *cp++ = *src++;
1182  count++;
1183  }
1184  *cp = '\0';
1185 
1186  if (!*src)
1187  break; /* bad format */
1188 
1189  src++; /* move past the trailing '>' (formerly '?') */
1190  }
1191 
1192  /* handle generic cases first */
1193  if ((ch == '>') || (ch == '*'))
1194  {
1195  /* %>X: right justify to EOL, left takes precedence
1196  * %*X: right justify to EOL, right takes precedence */
1197  int soft = ch == '*';
1198  int pl, pw;
1199  pl = mutt_mb_charlen(src, &pw);
1200  if (pl <= 0)
1201  {
1202  pl = 1;
1203  pw = 1;
1204  }
1205 
1206  /* see if there's room to add content, else ignore */
1207  if (((col < cols) && (wlen < buflen)) || soft)
1208  {
1209  int pad;
1210 
1211  /* get contents after padding */
1212  mutt_expando_format(tmp, sizeof(tmp), 0, cols, src + pl, callback, data, flags);
1213  len = mutt_str_strlen(tmp);
1214  wid = mutt_strwidth(tmp);
1215 
1216  pad = (cols - col - wid) / pw;
1217  if (pad >= 0)
1218  {
1219  /* try to consume as many columns as we can, if we don't have
1220  * memory for that, use as much memory as possible */
1221  if (wlen + (pad * pl) + len > buflen)
1222  pad = (buflen > (wlen + len)) ? ((buflen - wlen - len) / pl) : 0;
1223  else
1224  {
1225  /* Add pre-spacing to make multi-column pad characters and
1226  * the contents after padding line up */
1227  while ((col + (pad * pw) + wid < cols) && (wlen + (pad * pl) + len < buflen))
1228  {
1229  *wptr++ = ' ';
1230  wlen++;
1231  col++;
1232  }
1233  }
1234  while (pad-- > 0)
1235  {
1236  memcpy(wptr, src, pl);
1237  wptr += pl;
1238  wlen += pl;
1239  col += pw;
1240  }
1241  }
1242  else if (soft)
1243  {
1244  int offset = ((flags & MUTT_FORMAT_ARROWCURSOR) && C_ArrowCursor) ? 3 : 0;
1245  int avail_cols = (cols > offset) ? (cols - offset) : 0;
1246  /* \0-terminate buf for length computation in mutt_wstr_trunc() */
1247  *wptr = '\0';
1248  /* make sure right part is at most as wide as display */
1249  len = mutt_wstr_trunc(tmp, buflen, avail_cols, &wid);
1250  /* truncate left so that right part fits completely in */
1251  wlen = mutt_wstr_trunc(buf, buflen - len, avail_cols - wid, &col);
1252  wptr = buf + wlen;
1253  /* Multi-column characters may be truncated in the middle.
1254  * Add spacing so the right hand side lines up. */
1255  while ((col + wid < avail_cols) && (wlen + len < buflen))
1256  {
1257  *wptr++ = ' ';
1258  wlen++;
1259  col++;
1260  }
1261  }
1262  if ((len + wlen) > buflen)
1263  len = mutt_wstr_trunc(tmp, buflen - wlen, cols - col, NULL);
1264  memcpy(wptr, tmp, len);
1265  wptr += len;
1266  }
1267  break; /* skip rest of input */
1268  }
1269  else if (ch == '|')
1270  {
1271  /* pad to EOL */
1272  int pl, pw;
1273  pl = mutt_mb_charlen(src, &pw);
1274  if (pl <= 0)
1275  {
1276  pl = 1;
1277  pw = 1;
1278  }
1279 
1280  /* see if there's room to add content, else ignore */
1281  if ((col < cols) && (wlen < buflen))
1282  {
1283  int c = (cols - col) / pw;
1284  if ((c > 0) && (wlen + (c * pl) > buflen))
1285  c = ((signed) (buflen - wlen)) / pl;
1286  while (c > 0)
1287  {
1288  memcpy(wptr, src, pl);
1289  wptr += pl;
1290  wlen += pl;
1291  col += pw;
1292  c--;
1293  }
1294  }
1295  break; /* skip rest of input */
1296  }
1297  else
1298  {
1299  bool to_lower = false;
1300  bool no_dots = false;
1301 
1302  while ((ch == '_') || (ch == ':'))
1303  {
1304  if (ch == '_')
1305  to_lower = true;
1306  else if (ch == ':')
1307  no_dots = true;
1308 
1309  ch = *src++;
1310  }
1311 
1312  /* use callback function to handle this case */
1313  src = callback(tmp, sizeof(tmp), col, cols, ch, src, prefix, if_str,
1314  else_str, data, flags);
1315 
1316  if (to_lower)
1317  mutt_str_strlower(tmp);
1318  if (no_dots)
1319  {
1320  char *p = tmp;
1321  for (; *p; p++)
1322  if (*p == '.')
1323  *p = '_';
1324  }
1325 
1326  len = mutt_str_strlen(tmp);
1327  if ((len + wlen) > buflen)
1328  len = mutt_wstr_trunc(tmp, buflen - wlen, cols - col, NULL);
1329 
1330  memcpy(wptr, tmp, len);
1331  wptr += len;
1332  wlen += len;
1333  col += mutt_strwidth(tmp);
1334  }
1335  }
1336  else if (*src == '\\')
1337  {
1338  if (!*++src)
1339  break;
1340  switch (*src)
1341  {
1342  case 'f':
1343  *wptr = '\f';
1344  break;
1345  case 'n':
1346  *wptr = '\n';
1347  break;
1348  case 'r':
1349  *wptr = '\r';
1350  break;
1351  case 't':
1352  *wptr = '\t';
1353  break;
1354  case 'v':
1355  *wptr = '\v';
1356  break;
1357  default:
1358  *wptr = *src;
1359  break;
1360  }
1361  src++;
1362  wptr++;
1363  wlen++;
1364  col++;
1365  }
1366  else
1367  {
1368  int bytes, width;
1369  /* in case of error, simply copy byte */
1370  bytes = mutt_mb_charlen(src, &width);
1371  if (bytes < 0)
1372  {
1373  bytes = 1;
1374  width = 1;
1375  }
1376  if ((bytes > 0) && ((wlen + bytes) < buflen))
1377  {
1378  memcpy(wptr, src, bytes);
1379  wptr += bytes;
1380  src += bytes;
1381  wlen += bytes;
1382  col += width;
1383  }
1384  else
1385  {
1386  src += buflen - wlen;
1387  wlen = buflen;
1388  }
1389  }
1390  }
1391  *wptr = '\0';
1392 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:209
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:878
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
String manipulation buffer.
Definition: buffer.h:33
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
int mutt_mb_charlen(const char *s, int *width)
Count the bytes in a (multibyte) character.
Definition: mbyte.c:55
#define MoreArgs(buf)
Definition: buffer.h:43
char * mutt_str_strlower(char *s)
convert all characters in the string to lowercase
Definition: string.c:509
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:1287
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:2674
char * dptr
Current read/write position.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:35
size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
Work out how to truncate a widechar string.
Definition: curs_lib.c:1237
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
Log at debug level 1.
Definition: logging.h:40
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
#define MUTT_FORMAT_NOFILTER
Do not allow filtering on this pass.
Definition: format_flags.h:37
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Log at debug level 5.
Definition: logging.h:44
int mutt_wait_filter(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:220
static int pad(FILE *fp, int col, int i)
Write some padding to a file.
Definition: help.c:257
Log at debug level 3.
Definition: logging.h:42
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:76
WHERE bool C_ArrowCursor
Config: Use an arrow &#39;->&#39; instead of highlighting in the index.
Definition: globals.h:197
+ 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 134 of file muttlib.c.

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

358 {
359  struct Buffer *tmp = mutt_buffer_pool_get();
360 
361  mutt_buffer_addstr(tmp, NONULL(buf));
362  mutt_buffer_expand_path_regex(tmp, regex);
363  mutt_str_strfcpy(buf, mutt_b2s(tmp), buflen);
364 
366 
367  return buf;
368 }
#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:146
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
#define mutt_b2s(buf)
Definition: buffer.h:41
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
+ 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 C_GecosMask, 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 382 of file muttlib.c.

383 {
384  regmatch_t pat_match[1];
385  size_t pwnl;
386  char *p = NULL;
387 
388  if (!pw || !pw->pw_gecos)
389  return NULL;
390 
391  memset(dest, 0, destlen);
392 
393  if (mutt_regex_capture(C_GecosMask, pw->pw_gecos, 1, pat_match))
394  {
395  mutt_str_strfcpy(dest, pw->pw_gecos + pat_match[0].rm_so,
396  MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
397  }
398  else if ((p = strchr(pw->pw_gecos, ',')))
399  mutt_str_strfcpy(dest, pw->pw_gecos, MIN(destlen, p - pw->pw_gecos + 1));
400  else
401  mutt_str_strfcpy(dest, pw->pw_gecos, destlen);
402 
403  pwnl = strlen(pw->pw_name);
404 
405  for (int idx = 0; dest[idx]; idx++)
406  {
407  if (dest[idx] == '&')
408  {
409  memmove(&dest[idx + pwnl], &dest[idx + 1],
410  MAX((ssize_t)(destlen - idx - pwnl - 1), 0));
411  memcpy(&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl));
412  dest[idx] = toupper((unsigned char) dest[idx]);
413  }
414  }
415 
416  return dest;
417 }
#define MIN(a, b)
Definition: memory.h:31
#define MAX(a, b)
Definition: memory.h:30
struct Regex * C_GecosMask
Config: Regex for parsing GECOS field of /etc/passwd.
Definition: muttlib.c:72
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
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:594
+ 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 1656 of file muttlib.c.

1657 {
1658  enum MailboxType mb_magic = mx_path_probe(path, NULL);
1659 
1660  if (mb_magic == MUTT_IMAP)
1661  imap_get_parent_path(path, buf, buflen);
1662  else if (mb_magic == MUTT_NOTMUCH)
1663  mutt_str_strfcpy(buf, C_Folder, buflen);
1664  else
1665  {
1666  mutt_str_strfcpy(buf, path, buflen);
1667  int n = mutt_str_strlen(buf);
1668  if (n == 0)
1669  return;
1670 
1671  /* remove any final trailing '/' */
1672  if (buf[n - 1] == '/')
1673  buf[n - 1] = '\0';
1674 
1675  /* Remove everything until the next slash */
1676  for (n--; ((n >= 0) && (buf[n] != '/')); n--)
1677  ;
1678 
1679  if (n > 0)
1680  buf[n] = '\0';
1681  else
1682  {
1683  buf[0] = '/';
1684  buf[1] = '\0';
1685  }
1686  }
1687 }
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
Definition: util.c:300
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:120
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:53
MailboxType
Supported mailbox formats.
Definition: mailbox.h:42
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1290
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
+ 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
-1if a is INBOX of b
0if none is INBOX
1if b 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 1711 of file muttlib.c.

1712 {
1713  /* fast-track in case the paths have been mutt_pretty_mailbox'ified */
1714  if ((a[0] == '+') && (b[0] == '+'))
1715  {
1716  return (mutt_str_strcasecmp(a + 1, "inbox") == 0) ?
1717  -1 :
1718  (mutt_str_strcasecmp(b + 1, "inbox") == 0) ? 1 : 0;
1719  }
1720 
1721  const char *a_end = strrchr(a, '/');
1722  const char *b_end = strrchr(b, '/');
1723 
1724  /* If one path contains a '/', but not the other */
1725  if ((!a_end) ^ (!b_end))
1726  return 0;
1727 
1728  /* If neither path contains a '/' */
1729  if (!a_end)
1730  return 0;
1731 
1732  /* Compare the subpaths */
1733  size_t a_len = a_end - a;
1734  size_t b_len = b_end - b;
1735  size_t min = MIN(a_len, b_len);
1736  int same = (a[min] == '/') && (b[min] == '/') && (a[min + 1] != '\0') &&
1737  (b[min + 1] != '\0') && (mutt_str_strncasecmp(a, b, min) == 0);
1738 
1739  if (!same)
1740  return 0;
1741 
1742  if (mutt_str_strcasecmp(&a[min + 1], "inbox") == 0)
1743  return -1;
1744 
1745  if (mutt_str_strcasecmp(&b[min + 1], "inbox") == 0)
1746  return 1;
1747 
1748  return 0;
1749 }
#define MIN(a, b)
Definition: memory.h:31
int mutt_str_strncasecmp(const char *a, const char *b, size_t l)
Compare two strings ignoring case (to a maximum), safely.
Definition: string.c:656
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
+ 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
trueIf part is in plain text

Definition at line 453 of file muttlib.c.

454 {
455  int t = b->type;
456  char *s = b->subtype;
457 
459  return false;
460 
461  if (t == TYPE_TEXT)
462  return true;
463 
464  if (t == TYPE_MESSAGE)
465  {
466  if (mutt_str_strcasecmp("delivery-status", s) == 0)
467  return true;
468  }
469 
470  if (((WithCrypto & APPLICATION_PGP) != 0) && (t == TYPE_APPLICATION))
471  {
472  if (mutt_str_strcasecmp("pgp-keys", s) == 0)
473  return true;
474  }
475 
476  return false;
477 }
char * subtype
content-type subtype
Definition: body.h:37
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:559
Type: &#39;text/*&#39;.
Definition: mime.h:38
unsigned int type
content-type primary type
Definition: body.h:65
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
Type: &#39;message/*&#39;.
Definition: mime.h:35
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
#define WithCrypto
Definition: ncrypt.h:160
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 1560 of file muttlib.c.

1561 {
1562  static char vstring[256];
1563  snprintf(vstring, sizeof(vstring), "NeoMutt %s%s", PACKAGE_VERSION, GitVer);
1564  return vstring;
1565 }
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 599 of file muttlib.c.

601 {
602  size_t n =
603  snprintf(buf, buflen, "%s/%s-%s-%d-%d-%" PRIu64 "%s%s", NONULL(C_Tmpdir),
604  NONULL(prefix), NONULL(ShortHostname), (int) getuid(),
605  (int) getpid(), mutt_rand64(), suffix ? "." : "", NONULL(suffix));
606  if (n >= buflen)
607  {
609  "%s:%d: ERROR: insufficient buffer space to hold temporary "
610  "filename! buflen=%zu but need %zu\n",
611  src, line, buflen, n);
612  }
613  mutt_debug(LL_DEBUG3, "%s:%d: mutt_mktemp returns \"%s\"\n", src, line, buf);
614  if (unlink(buf) && (errno != ENOENT))
615  {
616  mutt_debug(LL_DEBUG1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src,
617  line, buf, strerror(errno), errno);
618  }
619 }
#define NONULL(x)
Definition: string2.h:37
const char * line
Definition: common.c:36
uint64_t mutt_rand64(void)
Create a 64-bit random number.
Definition: muttlib.c:556
Log at debug level 1.
Definition: logging.h:40
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:55
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:51
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
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 425 of file muttlib.c.

426 {
427  switch (m->type)
428  {
429  case TYPE_TEXT:
430  if (mutt_str_strcasecmp("plain", m->subtype) == 0)
431  return false;
432  break;
433  case TYPE_APPLICATION:
435  return false;
437  return false;
438  break;
439 
440  case TYPE_MULTIPART:
441  case TYPE_MESSAGE:
442  return false;
443  }
444 
445  return true;
446 }
char * subtype
content-type subtype
Definition: body.h:37
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:559
Type: &#39;text/*&#39;.
Definition: mime.h:38
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:618
unsigned int type
content-type primary type
Definition: body.h:65
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
Type: &#39;message/*&#39;.
Definition: mime.h:35
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
#define WithCrypto
Definition: ncrypt.h:160
Type: &#39;application/*&#39;.
Definition: mime.h:33
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:135
+ 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 1404 of file muttlib.c.

1405 {
1406  FILE *fp = NULL;
1407  struct stat s;
1408 
1409  size_t len = mutt_str_strlen(path);
1410  if (len == 0)
1411  {
1412  return NULL;
1413  }
1414 
1415  if (path[len - 1] == '|')
1416  {
1417  /* read from a pipe */
1418 
1419  char *p = mutt_str_strdup(path);
1420 
1421  p[len - 1] = 0;
1422  mutt_endwin();
1423  *thepid = mutt_create_filter(p, NULL, &fp, NULL);
1424  FREE(&p);
1425  }
1426  else
1427  {
1428  if (stat(path, &s) < 0)
1429  return NULL;
1430  if (S_ISDIR(s.st_mode))
1431  {
1432  errno = EINVAL;
1433  return NULL;
1434  }
1435  fp = fopen(path, "r");
1436  *thepid = -1;
1437  }
1438  return fp;
1439 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:209
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:544
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#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 628 of file muttlib.c.

629 {
630  if (!buf)
631  return;
632 
633  char *p = buf, *q = buf;
634  size_t len;
635  enum UrlScheme scheme;
636  char tmp[PATH_MAX];
637 
638  scheme = url_check_scheme(buf);
639 
640  if ((scheme == U_IMAP) || (scheme == U_IMAPS))
641  {
642  imap_pretty_mailbox(buf, buflen, C_Folder);
643  return;
644  }
645 
646  if (scheme == U_NOTMUCH)
647  return;
648 
649  /* if buf is an url, only collapse path component */
650  if (scheme != U_UNKNOWN)
651  {
652  p = strchr(buf, ':') + 1;
653  if (strncmp(p, "//", 2) == 0)
654  q = strchr(p + 2, '/');
655  if (!q)
656  q = strchr(p, '\0');
657  p = q;
658  }
659 
660  /* cleanup path */
661  if (strstr(p, "//") || strstr(p, "/./"))
662  {
663  /* first attempt to collapse the pathname, this is more
664  * lightweight than realpath() and doesn't resolve links */
665  while (*p)
666  {
667  if ((p[0] == '/') && (p[1] == '/'))
668  {
669  *q++ = '/';
670  p += 2;
671  }
672  else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
673  {
674  *q++ = '/';
675  p += 3;
676  }
677  else
678  *q++ = *p++;
679  }
680  *q = '\0';
681  }
682  else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
683  realpath(p, tmp))
684  {
685  mutt_str_strfcpy(p, tmp, buflen - (p - buf));
686  }
687 
688  if ((len = mutt_str_startswith(buf, C_Folder, CASE_MATCH)) && (buf[len] == '/'))
689  {
690  *buf++ = '=';
691  memmove(buf, buf + len, mutt_str_strlen(buf + len) + 1);
692  }
693  else if ((len = mutt_str_startswith(buf, HomeDir, CASE_MATCH)) && (buf[len] == '/'))
694  {
695  *buf++ = '~';
696  memmove(buf, buf + len - 1, mutt_str_strlen(buf + len - 1) + 1);
697  }
698 }
Url is notmuch://.
Definition: url.h:45
Url is imaps://.
Definition: url.h:39
Url wasn&#39;t recognised.
Definition: url.h:34
Url is imap://.
Definition: url.h:38
Match case when comparing strings.
Definition: string2.h:67
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
enum UrlScheme url_check_scheme(const char *s)
Check the protocol of a URL.
Definition: url.c:132
UrlScheme
All recognised Url types.
Definition: url.h:32
WHERE char * HomeDir
User&#39;s home directory.
Definition: globals.h:50
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:120
#define PATH_MAX
Definition: mutt.h:50
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:703
Url is file://.
Definition: url.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_rand32()

uint32_t mutt_rand32 ( void  )

Create a 32-bit random number.

Return values
numRandom number

Definition at line 543 of file muttlib.c.

544 {
545  uint32_t num = 0;
546 
547  if (mutt_randbuf(&num, sizeof(num)) < 0)
548  mutt_exit(1);
549  return num;
550 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:486
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:210
+ Here is the call graph for this function:

◆ mutt_rand64()

uint64_t mutt_rand64 ( void  )

Create a 64-bit random number.

Return values
numRandom number

Definition at line 556 of file muttlib.c.

557 {
558  uint64_t num = 0;
559 
560  if (mutt_randbuf(&num, sizeof(num)) < 0)
561  mutt_exit(1);
562  return num;
563 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:486
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:210
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_rand_base32()

void mutt_rand_base32 ( void *  buf,
size_t  buflen 
)

Fill a buffer with a base32-encoded random string.

Parameters
bufBuffer for result
buflenLength of buffer

Definition at line 529 of file muttlib.c.

530 {
531  uint8_t *p = buf;
532 
533  if (mutt_randbuf(p, buflen) < 0)
534  mutt_exit(1);
535  for (size_t pos = 0; pos < buflen; pos++)
536  p[pos] = base32[p[pos] % 32];
537 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:486
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:210
static const unsigned char base32[]
Definition: muttlib.c:76
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_randbuf()

int mutt_randbuf ( void *  buf,
size_t  buflen 
)

Fill a buffer with randomness.

Parameters
bufBuffer for result
buflenSize of buffer
Return values
0Success
-1Error

Definition at line 486 of file muttlib.c.

487 {
488  if (buflen > 1048576)
489  {
490  mutt_error(_("mutt_randbuf buflen=%zu"), buflen);
491  return -1;
492  }
493 /* XXX switch to HAVE_GETRANDOM and getrandom() in about 2017 */
494 #if defined(SYS_getrandom) && defined(__linux__)
495  long ret;
496  do
497  {
498  ret = syscall(SYS_getrandom, buf, buflen, 0, 0, 0, 0);
499  } while ((ret == -1) && (errno == EINTR));
500  if (ret == buflen)
501  return 0;
502 #endif
503  /* let's try urandom in case we're on an old kernel, or the user has
504  * configured selinux, seccomp or something to not allow getrandom */
505  if (!fp_random)
506  {
507  fp_random = fopen("/dev/urandom", "rb");
508  if (!fp_random)
509  {
510  mutt_error(_("open /dev/urandom: %s"), strerror(errno));
511  return -1;
512  }
513  setbuf(fp_random, NULL);
514  }
515  if (fread(buf, 1, buflen, fp_random) != buflen)
516  {
517  mutt_error(_("read /dev/urandom: %s"), strerror(errno));
518  return -1;
519  }
520 
521  return 0;
522 }
#define _(a)
Definition: message.h:28
static FILE * fp_random
Definition: muttlib.c:74
#define mutt_error(...)
Definition: logging.h:84
+ 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 859 of file muttlib.c.

860 {
861  mutt_buffer_save_path(dest, a);
862  for (char *p = dest->data; *p; p++)
863  if ((*p == '/') || IS_SPACE(*p) || !IsPrint((unsigned char) *p))
864  *p = '_';
865 }
void mutt_buffer_save_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
Definition: muttlib.c:832
#define IsPrint(ch)
Definition: mbyte.h:39
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
0if OK to proceed
-1to abort
1to retry

Definition at line 1449 of file muttlib.c.

1450 {
1451  int ret = 0;
1452 
1453  enum MailboxType magic = mx_path_probe(s, NULL);
1454 
1455 #ifdef USE_POP
1456  if (magic == MUTT_POP)
1457  {
1458  mutt_error(_("Can't save message to POP mailbox"));
1459  return 1;
1460  }
1461 #endif
1462 
1463  if ((magic != MUTT_MAILBOX_ERROR) && (magic != MUTT_UNKNOWN) && !mx_access(s, W_OK))
1464  {
1465  if (C_Confirmappend)
1466  {
1467  struct Buffer *tmp = mutt_buffer_pool_get();
1468  mutt_buffer_printf(tmp, _("Append messages to %s?"), s);
1469  enum QuadOption ans = mutt_yesorno(mutt_b2s(tmp), MUTT_YES);
1470  if (ans == MUTT_NO)
1471  ret = 1;
1472  else if (ans == MUTT_ABORT)
1473  ret = -1;
1475  }
1476  }
1477 
1478 #ifdef USE_NNTP
1479  if (magic == MUTT_NNTP)
1480  {
1481  mutt_error(_("Can't save message to news server"));
1482  return 0;
1483  }
1484 #endif
1485 
1486  if (stat(s, st) != -1)
1487  {
1488  if (magic == MUTT_MAILBOX_ERROR)
1489  {
1490  mutt_error(_("%s is not a mailbox"), s);
1491  return 1;
1492  }
1493  }
1494  else if (magic != MUTT_IMAP)
1495  {
1496  st->st_mtime = 0;
1497  st->st_atime = 0;
1498 
1499  /* pathname does not exist */
1500  if (errno == ENOENT)
1501  {
1502  if (C_Confirmcreate)
1503  {
1504  struct Buffer *tmp = mutt_buffer_pool_get();
1505  mutt_buffer_printf(tmp, _("Create %s?"), s);
1506  enum QuadOption ans = mutt_yesorno(mutt_b2s(tmp), MUTT_YES);
1507  if (ans == MUTT_NO)
1508  ret = 1;
1509  else if (ans == MUTT_ABORT)
1510  ret = -1;
1512  }
1513 
1514  /* user confirmed with MUTT_YES or set C_Confirmcreate */
1515  if (ret == 0)
1516  {
1517  /* create dir recursively */
1518  char *tmp_path = mutt_path_dirname(s);
1519  if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
1520  {
1521  /* report failure & abort */
1522  mutt_perror(s);
1523  FREE(&tmp_path);
1524  return 1;
1525  }
1526  FREE(&tmp_path);
1527  }
1528  }
1529  else
1530  {
1531  mutt_perror(s);
1532  return 1;
1533  }
1534  }
1535 
1537  return ret;
1538 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:51
User aborted the question (with Ctrl-G)
Definition: quad.h:37
WHERE bool C_Confirmappend
Config: Confirm before appending emails to a mailbox.
Definition: globals.h:211
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final &#39;/&#39;.
Definition: path.c:354
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
#define _(a)
Definition: message.h:28
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:46
Error occurred examining Mailbox.
Definition: mailbox.h:45
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
WHERE bool C_Confirmcreate
Config: Confirm before creating a new mailbox.
Definition: globals.h:212
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:375
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:873
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:95
#define mutt_b2s(buf)
Definition: buffer.h:41
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:54
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
MailboxType
Supported mailbox formats.
Definition: mailbox.h:42
#define mutt_error(...)
Definition: logging.h:84
#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:169
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:42
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1290
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
+ 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 810 of file muttlib.c.

811 {
812  if (addr && addr->mailbox)
813  {
814  mutt_str_strfcpy(buf, addr->mailbox, buflen);
815  if (!C_SaveAddress)
816  {
817  char *p = strpbrk(buf, "%@");
818  if (p)
819  *p = '\0';
820  }
821  mutt_str_strlower(buf);
822  }
823  else
824  *buf = '\0';
825 }
char * mailbox
Mailbox and host address.
Definition: address.h:37
char * mutt_str_strlower(char *s)
convert all characters in the string to lowercase
Definition: string.c:509
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
WHERE bool C_SaveAddress
Config: Use sender&#39;s full address as a default save folder.
Definition: globals.h:252
+ 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 1546 of file muttlib.c.

1547 {
1548  if (C_SleepTime > s)
1549  sleep(C_SleepTime);
1550  else if (s)
1551  sleep(s);
1552 }
WHERE short C_SleepTime
Config: Time to pause after certain info messages.
Definition: globals.h:151
+ 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 1779 of file muttlib.c.

1780 {
1781  if (!buf || (buflen == 0))
1782  return;
1783 
1784  if (C_SizeShowBytes && (num < 1024))
1785  {
1786  snprintf(buf, buflen, "%d", (int) num);
1787  }
1788  else if (num == 0)
1789  {
1790  mutt_str_strfcpy(buf, C_SizeUnitsOnLeft ? "K0" : "0K", buflen);
1791  }
1792  else if (C_SizeShowFractions && (num < 10189)) /* 0.1K - 9.9K */
1793  {
1794  snprintf(buf, buflen, C_SizeUnitsOnLeft ? "K%3.1f" : "%3.1fK",
1795  (num < 103) ? 0.1 : (num / 1024.0));
1796  }
1797  else if (!C_SizeShowMb || (num < 1023949)) /* 10K - 999K */
1798  {
1799  /* 51 is magic which causes 10189/10240 to be rounded up to 10 */
1800  snprintf(buf, buflen, C_SizeUnitsOnLeft ? ("K%zu") : ("%zuK"), (num + 51) / 1024);
1801  }
1802  else if (C_SizeShowFractions && (num < 10433332)) /* 1.0M - 9.9M */
1803  {
1804  snprintf(buf, buflen, C_SizeUnitsOnLeft ? "M%3.1f" : "%3.1fM", num / 1048576.0);
1805  }
1806  else /* 10M+ */
1807  {
1808  /* (10433332 + 52428) / 1048576 = 10 */
1809  snprintf(buf, buflen, C_SizeUnitsOnLeft ? ("M%zu") : ("%zuM"), (num + 52428) / 1048576);
1810  }
1811 }
WHERE bool C_SizeShowFractions
Config: Show size fractions with a single decimal place.
Definition: globals.h:260
WHERE bool C_SizeShowMb
Config: Show sizes in megabytes for sizes greater than 1 megabyte.
Definition: globals.h:261
WHERE bool C_SizeUnitsOnLeft
Config: Show the units as a prefix to the size.
Definition: globals.h:262
WHERE bool C_SizeShowBytes
Config: Show smaller sizes in bytes.
Definition: globals.h:259
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ C_GecosMask

struct Regex* C_GecosMask

Config: Regex for parsing GECOS field of /etc/passwd.

Definition at line 72 of file muttlib.c.