NeoMutt  2019-12-07-60-g0cfa53
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 95 of file muttlib.c.

96 {
97  if (!(buf->data && buf->data[0]))
98  {
99  mutt_buffer_mktemp(buf);
100  }
101  else
102  {
103  struct Buffer *prefix = mutt_buffer_pool_get();
104  mutt_buffer_strcpy(prefix, buf->data);
105  mutt_file_sanitize_filename(prefix->data, true);
106  mutt_buffer_printf(buf, "%s/%s", NONULL(C_Tmpdir), mutt_b2s(prefix));
107 
108  struct stat sb;
109  if ((lstat(mutt_b2s(buf), &sb) == -1) && (errno == ENOENT))
110  goto out;
111 
112  char *suffix = strchr(prefix->data, '.');
113  if (suffix)
114  {
115  *suffix = '\0';
116  suffix++;
117  }
118  mutt_buffer_mktemp_pfx_sfx(buf, prefix->data, suffix);
119 
120  out:
121  mutt_buffer_pool_release(&prefix);
122  }
123 }
#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 572 of file muttlib.c.

574 {
575  mutt_buffer_printf(buf, "%s/%s-%s-%d-%d-%" PRIu64 "%s%s", NONULL(C_Tmpdir),
576  NONULL(prefix), NONULL(ShortHostname), (int) getuid(),
577  (int) getpid(), mutt_rand64(), suffix ? "." : "", NONULL(suffix));
578 
579  mutt_debug(LL_DEBUG3, "%s:%d: mutt_mktemp returns \"%s\"\n", src, line, mutt_b2s(buf));
580  if (unlink(mutt_b2s(buf)) && (errno != ENOENT))
581  {
582  mutt_debug(LL_DEBUG1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src,
583  line, mutt_b2s(buf), strerror(errno), errno);
584  }
585 }
#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:555
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:50
#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 1599 of file muttlib.c.

1600 {
1601  char *p = mutt_str_strdup(src);
1602  int rc = mutt_ch_convert_string(&p, C_Charset, "utf-8", 0);
1603  mutt_buffer_strcpy(buf, (rc == 0) ? NONULL(p) : NONULL(src));
1604  FREE(&p);
1605 }
#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 342 of file muttlib.c.

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

146 {
147  const char *s = NULL;
148  const char *tail = "";
149 
150  bool recurse = false;
151 
152  struct Buffer *p = mutt_buffer_pool_get();
153  struct Buffer *q = mutt_buffer_pool_get();
154  struct Buffer *tmp = mutt_buffer_pool_get();
155 
156  do
157  {
158  recurse = false;
159  s = mutt_b2s(buf);
160 
161  switch (*s)
162  {
163  case '~':
164  {
165  if ((s[1] == '/') || (s[1] == '\0'))
166  {
168  tail = s + 1;
169  }
170  else
171  {
172  char *t = strchr(s + 1, '/');
173  if (t)
174  *t = '\0';
175 
176  struct passwd *pw = getpwnam(s + 1);
177  if (pw)
178  {
179  mutt_buffer_strcpy(p, pw->pw_dir);
180  if (t)
181  {
182  *t = '/';
183  tail = t;
184  }
185  else
186  tail = "";
187  }
188  else
189  {
190  /* user not found! */
191  if (t)
192  *t = '/';
194  tail = s;
195  }
196  }
197  break;
198  }
199 
200  case '=':
201  case '+':
202  {
203  enum MailboxType mb_type = mx_path_probe(C_Folder, NULL);
204 
205  /* if folder = {host} or imap[s]://host/: don't append slash */
206  if ((mb_type == MUTT_IMAP) && ((C_Folder[strlen(C_Folder) - 1] == '}') ||
207  (C_Folder[strlen(C_Folder) - 1] == '/')))
208  {
210  }
211  else if (mb_type == MUTT_NOTMUCH)
213  else if (C_Folder && (C_Folder[strlen(C_Folder) - 1] == '/'))
215  else
216  mutt_buffer_printf(p, "%s/", NONULL(C_Folder));
217 
218  tail = s + 1;
219  break;
220  }
221 
222  /* elm compatibility, @ expands alias to user name */
223 
224  case '@':
225  {
226  struct AddressList *al = mutt_alias_lookup(s + 1);
227  if (!TAILQ_EMPTY(al))
228  {
229  struct Email *e = email_new();
230  e->env = mutt_env_new();
231  mutt_addrlist_copy(&e->env->from, al, false);
232  mutt_addrlist_copy(&e->env->to, al, false);
233 
234  /* TODO: fix mutt_default_save() to use Buffer */
236  mutt_default_save(p->data, p->dsize, e);
238 
239  email_free(&e);
240  /* Avoid infinite recursion if the resulting folder starts with '@' */
241  if (*p->data != '@')
242  recurse = true;
243 
244  tail = "";
245  }
246  break;
247  }
248 
249  case '>':
250  {
252  tail = s + 1;
253  break;
254  }
255 
256  case '<':
257  {
259  tail = s + 1;
260  break;
261  }
262 
263  case '!':
264  {
265  if (s[1] == '!')
266  {
268  tail = s + 2;
269  }
270  else
271  {
273  tail = s + 1;
274  }
275  break;
276  }
277 
278  case '-':
279  {
281  tail = s + 1;
282  break;
283  }
284 
285  case '^':
286  {
288  tail = s + 1;
289  break;
290  }
291 
292  default:
293  {
295  tail = s;
296  }
297  }
298 
299  if (regex && *(mutt_b2s(p)) && !recurse)
300  {
302  mutt_buffer_printf(tmp, "%s%s", mutt_b2s(q), tail);
303  }
304  else
305  mutt_buffer_printf(tmp, "%s%s", mutt_b2s(p), tail);
306 
307  mutt_buffer_copy(buf, tmp);
308  } while (recurse);
309 
313 
314 #ifdef USE_IMAP
315  /* Rewrite IMAP path in canonical form - aids in string comparisons of
316  * folders. May possibly fail, in which case buf should be the same. */
317  if (imap_path_probe(mutt_b2s(buf), NULL) == MUTT_IMAP)
318  imap_expand_path(buf);
319  else
320 #endif
321  {
322  /* Resolve symbolic links */
323  struct stat st;
324  int rc = lstat(mutt_b2s(buf), &st);
325  if ((rc != -1) && S_ISLNK(st.st_mode))
326  {
327  char path[PATH_MAX];
328  if (realpath(mutt_b2s(buf), path))
329  {
330  mutt_buffer_strcpy(buf, path);
331  }
332  }
333  }
334 }
#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:728
String manipulation buffer.
Definition: buffer.h:33
WHERE char * LastFolder
Previously selected mailbox.
Definition: globals.h:55
WHERE char * C_Record
Config: Folder to save &#39;sent&#39; messages.
Definition: globals.h:131
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:117
struct Envelope * env
Envelope information.
Definition: email.h:89
WHERE char * HomeDir
User&#39;s home directory.
Definition: globals.h:49
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: globals.h:54
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:119
#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:144
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:714
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:1288
&#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 703 of file muttlib.c.

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

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

832 {
833  if (a && a->mailbox)
834  {
835  mutt_buffer_strcpy(dest, a->mailbox);
836  if (!C_SaveAddress)
837  {
838  char *p = strpbrk(dest->data, "%@");
839  if (p)
840  {
841  *p = '\0';
842  mutt_buffer_fix_dptr(dest);
843  }
844  }
845  mutt_str_strlower(dest->data);
846  }
847  else
848  mutt_buffer_reset(dest);
849 }
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:248
+ 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 725 of file muttlib.c.

727 {
728  struct stat st;
729 
730  mutt_buffer_strcpy(fname, path);
731  if (access(mutt_b2s(fname), F_OK) != 0)
732  return 0;
733  if (stat(mutt_b2s(fname), &st) != 0)
734  return -1;
735  if (S_ISDIR(st.st_mode))
736  {
737  enum QuadOption ans = MUTT_NO;
738  if (directory)
739  {
740  switch (mutt_multi_choice
741  /* L10N: Means "The path you specified as the destination file is a directory."
742  See the msgid "Save to file: " (alias.c, recvattach.c)
743  These three letters correspond to the choices in the string. */
744  (_("File is a directory, save under it: (y)es, (n)o, (a)ll?"), _("yna")))
745  {
746  case 3: /* all */
747  mutt_str_replace(directory, mutt_b2s(fname));
748  break;
749  case 1: /* yes */
750  FREE(directory);
751  break;
752  case -1: /* abort */
753  FREE(directory);
754  return -1;
755  case 2: /* no */
756  FREE(directory);
757  return 1;
758  }
759  }
760  /* L10N: Means "The path you specified as the destination file is a directory."
761  See the msgid "Save to file: " (alias.c, recvattach.c) */
762  else if ((ans = mutt_yesorno(_("File is a directory, save under it?"), MUTT_YES)) != MUTT_YES)
763  return (ans == MUTT_NO) ? 1 : -1;
764 
765  struct Buffer *tmp = mutt_buffer_pool_get();
767  if ((mutt_buffer_get_field(_("File under directory: "), tmp, MUTT_FILE | MUTT_CLEAR) != 0) ||
769  {
771  return (-1);
772  }
773  mutt_buffer_concat_path(fname, path, mutt_b2s(tmp));
775  }
776 
777  if ((*opt == MUTT_SAVE_NO_FLAGS) && (access(mutt_b2s(fname), F_OK) == 0))
778  {
779  switch (
780  mutt_multi_choice(_("File exists, (o)verwrite, (a)ppend, or (c)ancel?"),
781  // L10N: Options for: File exists, (o)verwrite, (a)ppend, or (c)ancel?
782  _("oac")))
783  {
784  case -1: /* abort */
785  return -1;
786  case 3: /* cancel */
787  return 1;
788 
789  case 2: /* append */
790  *opt = MUTT_SAVE_APPEND;
791  break;
792  case 1: /* overwrite */
793  *opt = MUTT_SAVE_OVERWRITE;
794  break;
795  }
796  }
797  return 0;
798 }
#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:40
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:376
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:933
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
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:85
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:36
+ 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 1574 of file muttlib.c.

1575 {
1576  char *p = mutt_str_strdup(src);
1577  int rc = mutt_ch_convert_string(&p, C_Charset, "us-ascii", 0);
1578  /* 'src' may be NULL, such as when called from the pop3 driver. */
1579  size_t len = mutt_str_strfcpy(buf, (rc == 0) ? p : src, buflen);
1580 
1581  /* convert the path to POSIX "Portable Filename Character Set" */
1582  for (size_t i = 0; i < len; i++)
1583  {
1584  if (!isalnum(buf[i]) && !strchr("/.-_", buf[i]))
1585  {
1586  buf[i] = '_';
1587  }
1588  }
1589  FREE(&p);
1590 }
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 877 of file muttlib.c.

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

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

357 {
358  struct Buffer *tmp = mutt_buffer_pool_get();
359 
360  mutt_buffer_addstr(tmp, NONULL(buf));
361  mutt_buffer_expand_path_regex(tmp, regex);
362  mutt_str_strfcpy(buf, mutt_b2s(tmp), buflen);
363 
365 
366  return buf;
367 }
#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:145
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 381 of file muttlib.c.

382 {
383  regmatch_t pat_match[1];
384  size_t pwnl;
385  char *p = NULL;
386 
387  if (!pw || !pw->pw_gecos)
388  return NULL;
389 
390  memset(dest, 0, destlen);
391 
392  if (mutt_regex_capture(C_GecosMask, pw->pw_gecos, 1, pat_match))
393  {
394  mutt_str_strfcpy(dest, pw->pw_gecos + pat_match[0].rm_so,
395  MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
396  }
397  else if ((p = strchr(pw->pw_gecos, ',')))
398  mutt_str_strfcpy(dest, pw->pw_gecos, MIN(destlen, p - pw->pw_gecos + 1));
399  else
400  mutt_str_strfcpy(dest, pw->pw_gecos, destlen);
401 
402  pwnl = strlen(pw->pw_name);
403 
404  for (int idx = 0; dest[idx]; idx++)
405  {
406  if (dest[idx] == '&')
407  {
408  memmove(&dest[idx + pwnl], &dest[idx + 1],
409  MAX((ssize_t)(destlen - idx - pwnl - 1), 0));
410  memcpy(&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl));
411  dest[idx] = toupper((unsigned char) dest[idx]);
412  }
413  }
414 
415  return dest;
416 }
#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:71
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 1655 of file muttlib.c.

1656 {
1657  enum MailboxType mb_magic = mx_path_probe(path, NULL);
1658 
1659  if (mb_magic == MUTT_IMAP)
1660  imap_get_parent_path(path, buf, buflen);
1661  else if (mb_magic == MUTT_NOTMUCH)
1662  mutt_str_strfcpy(buf, C_Folder, buflen);
1663  else
1664  {
1665  mutt_str_strfcpy(buf, path, buflen);
1666  int n = mutt_str_strlen(buf);
1667  if (n == 0)
1668  return;
1669 
1670  /* remove any final trailing '/' */
1671  if (buf[n - 1] == '/')
1672  buf[n - 1] = '\0';
1673 
1674  /* Remove everything until the next slash */
1675  for (n--; ((n >= 0) && (buf[n] != '/')); n--)
1676  ;
1677 
1678  if (n > 0)
1679  buf[n] = '\0';
1680  else
1681  {
1682  buf[0] = '/';
1683  buf[1] = '\0';
1684  }
1685  }
1686 }
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:303
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:119
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:1288
&#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 1710 of file muttlib.c.

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

453 {
454  int t = b->type;
455  char *s = b->subtype;
456 
458  return false;
459 
460  if (t == TYPE_TEXT)
461  return true;
462 
463  if (t == TYPE_MESSAGE)
464  {
465  if (mutt_str_strcasecmp("delivery-status", s) == 0)
466  return true;
467  }
468 
469  if (((WithCrypto & APPLICATION_PGP) != 0) && (t == TYPE_APPLICATION))
470  {
471  if (mutt_str_strcasecmp("pgp-keys", s) == 0)
472  return true;
473  }
474 
475  return false;
476 }
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:557
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 1559 of file muttlib.c.

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

600 {
601  size_t n =
602  snprintf(buf, buflen, "%s/%s-%s-%d-%d-%" PRIu64 "%s%s", NONULL(C_Tmpdir),
603  NONULL(prefix), NONULL(ShortHostname), (int) getuid(),
604  (int) getpid(), mutt_rand64(), suffix ? "." : "", NONULL(suffix));
605  if (n >= buflen)
606  {
608  "%s:%d: ERROR: insufficient buffer space to hold temporary "
609  "filename! buflen=%zu but need %zu\n",
610  src, line, buflen, n);
611  }
612  mutt_debug(LL_DEBUG3, "%s:%d: mutt_mktemp returns \"%s\"\n", src, line, buf);
613  if (unlink(buf) && (errno != ENOENT))
614  {
615  mutt_debug(LL_DEBUG1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src,
616  line, buf, strerror(errno), errno);
617  }
618 }
#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:555
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:50
#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 424 of file muttlib.c.

425 {
426  switch (m->type)
427  {
428  case TYPE_TEXT:
429  if (mutt_str_strcasecmp("plain", m->subtype) == 0)
430  return false;
431  break;
432  case TYPE_APPLICATION:
434  return false;
436  return false;
437  break;
438 
439  case TYPE_MULTIPART:
440  case TYPE_MESSAGE:
441  return false;
442  }
443 
444  return true;
445 }
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:557
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:616
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 1403 of file muttlib.c.

1404 {
1405  FILE *fp = NULL;
1406  struct stat s;
1407 
1408  size_t len = mutt_str_strlen(path);
1409  if (len == 0)
1410  {
1411  return NULL;
1412  }
1413 
1414  if (path[len - 1] == '|')
1415  {
1416  /* read from a pipe */
1417 
1418  char *p = mutt_str_strdup(path);
1419 
1420  p[len - 1] = 0;
1421  mutt_endwin();
1422  *thepid = mutt_create_filter(p, NULL, &fp, NULL);
1423  FREE(&p);
1424  }
1425  else
1426  {
1427  if (stat(path, &s) < 0)
1428  return NULL;
1429  if (S_ISDIR(s.st_mode))
1430  {
1431  errno = EINVAL;
1432  return NULL;
1433  }
1434  fp = fopen(path, "r");
1435  *thepid = -1;
1436  }
1437  return fp;
1438 }
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:545
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 627 of file muttlib.c.

628 {
629  if (!buf)
630  return;
631 
632  char *p = buf, *q = buf;
633  size_t len;
634  enum UrlScheme scheme;
635  char tmp[PATH_MAX];
636 
637  scheme = url_check_scheme(buf);
638 
639  if ((scheme == U_IMAP) || (scheme == U_IMAPS))
640  {
641  imap_pretty_mailbox(buf, buflen, C_Folder);
642  return;
643  }
644 
645  if (scheme == U_NOTMUCH)
646  return;
647 
648  /* if buf is an url, only collapse path component */
649  if (scheme != U_UNKNOWN)
650  {
651  p = strchr(buf, ':') + 1;
652  if (strncmp(p, "//", 2) == 0)
653  q = strchr(p + 2, '/');
654  if (!q)
655  q = strchr(p, '\0');
656  p = q;
657  }
658 
659  /* cleanup path */
660  if (strstr(p, "//") || strstr(p, "/./"))
661  {
662  /* first attempt to collapse the pathname, this is more
663  * lightweight than realpath() and doesn't resolve links */
664  while (*p)
665  {
666  if ((p[0] == '/') && (p[1] == '/'))
667  {
668  *q++ = '/';
669  p += 2;
670  }
671  else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
672  {
673  *q++ = '/';
674  p += 3;
675  }
676  else
677  *q++ = *p++;
678  }
679  *q = '\0';
680  }
681  else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
682  realpath(p, tmp))
683  {
684  mutt_str_strfcpy(p, tmp, buflen - (p - buf));
685  }
686 
687  if ((len = mutt_str_startswith(buf, C_Folder, CASE_MATCH)) && (buf[len] == '/'))
688  {
689  *buf++ = '=';
690  memmove(buf, buf + len, mutt_str_strlen(buf + len) + 1);
691  }
692  else if ((len = mutt_str_startswith(buf, HomeDir, CASE_MATCH)) && (buf[len] == '/'))
693  {
694  *buf++ = '~';
695  memmove(buf, buf + len - 1, mutt_str_strlen(buf + len - 1) + 1);
696  }
697 }
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:49
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:119
#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:706
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 542 of file muttlib.c.

543 {
544  uint32_t num = 0;
545 
546  if (mutt_randbuf(&num, sizeof(num)) < 0)
547  mutt_exit(1);
548  return num;
549 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:485
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:207
+ 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 555 of file muttlib.c.

556 {
557  uint64_t num = 0;
558 
559  if (mutt_randbuf(&num, sizeof(num)) < 0)
560  mutt_exit(1);
561  return num;
562 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:485
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:207
+ 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 528 of file muttlib.c.

529 {
530  uint8_t *p = buf;
531 
532  if (mutt_randbuf(p, buflen) < 0)
533  mutt_exit(1);
534  for (size_t pos = 0; pos < buflen; pos++)
535  p[pos] = base32[p[pos] % 32];
536 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:485
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:207
static const unsigned char base32[]
Definition: muttlib.c:75
+ 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 485 of file muttlib.c.

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

859 {
860  mutt_buffer_save_path(dest, a);
861  for (char *p = dest->data; *p; p++)
862  if ((*p == '/') || IS_SPACE(*p) || !IsPrint((unsigned char) *p))
863  *p = '_';
864 }
void mutt_buffer_save_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
Definition: muttlib.c:831
#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 1448 of file muttlib.c.

1449 {
1450  int ret = 0;
1451 
1452  enum MailboxType magic = mx_path_probe(s, NULL);
1453 
1454 #ifdef USE_POP
1455  if (magic == MUTT_POP)
1456  {
1457  mutt_error(_("Can't save message to POP mailbox"));
1458  return 1;
1459  }
1460 #endif
1461 
1462  if ((magic != MUTT_MAILBOX_ERROR) && (magic != MUTT_UNKNOWN) && !mx_access(s, W_OK))
1463  {
1464  if (C_Confirmappend)
1465  {
1466  struct Buffer *tmp = mutt_buffer_pool_get();
1467  mutt_buffer_printf(tmp, _("Append messages to %s?"), s);
1468  enum QuadOption ans = mutt_yesorno(mutt_b2s(tmp), MUTT_YES);
1469  if (ans == MUTT_NO)
1470  ret = 1;
1471  else if (ans == MUTT_ABORT)
1472  ret = -1;
1474  }
1475  }
1476 
1477 #ifdef USE_NNTP
1478  if (magic == MUTT_NNTP)
1479  {
1480  mutt_error(_("Can't save message to news server"));
1481  return 0;
1482  }
1483 #endif
1484 
1485  if (stat(s, st) != -1)
1486  {
1487  if (magic == MUTT_MAILBOX_ERROR)
1488  {
1489  mutt_error(_("%s is not a mailbox"), s);
1490  return 1;
1491  }
1492  }
1493  else if (magic != MUTT_IMAP)
1494  {
1495  st->st_mtime = 0;
1496  st->st_atime = 0;
1497 
1498  /* pathname does not exist */
1499  if (errno == ENOENT)
1500  {
1501  if (C_Confirmcreate)
1502  {
1503  struct Buffer *tmp = mutt_buffer_pool_get();
1504  mutt_buffer_printf(tmp, _("Create %s?"), s);
1505  enum QuadOption ans = mutt_yesorno(mutt_b2s(tmp), MUTT_YES);
1506  if (ans == MUTT_NO)
1507  ret = 1;
1508  else if (ans == MUTT_ABORT)
1509  ret = -1;
1511  }
1512 
1513  /* user confirmed with MUTT_YES or set C_Confirmcreate */
1514  if (ret == 0)
1515  {
1516  /* create dir recursively */
1517  char *tmp_path = mutt_path_dirname(s);
1518  if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
1519  {
1520  /* report failure & abort */
1521  mutt_perror(s);
1522  FREE(&tmp_path);
1523  return 1;
1524  }
1525  FREE(&tmp_path);
1526  }
1527  }
1528  else
1529  {
1530  mutt_perror(s);
1531  return 1;
1532  }
1533  }
1534 
1536  return ret;
1537 }
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:38
WHERE bool C_Confirmappend
Config: Confirm before appending emails to a mailbox.
Definition: globals.h:207
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
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:208
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:376
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:113
#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:39
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:47
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1288
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
+ 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 809 of file muttlib.c.

810 {
811  if (addr && addr->mailbox)
812  {
813  mutt_str_strfcpy(buf, addr->mailbox, buflen);
814  if (!C_SaveAddress)
815  {
816  char *p = strpbrk(buf, "%@");
817  if (p)
818  *p = '\0';
819  }
820  mutt_str_strlower(buf);
821  }
822  else
823  *buf = '\0';
824 }
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:248
+ 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 1545 of file muttlib.c.

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

1779 {
1780  if (!buf || (buflen == 0))
1781  return;
1782 
1783  if (C_SizeShowBytes && (num < 1024))
1784  {
1785  snprintf(buf, buflen, "%d", (int) num);
1786  }
1787  else if (num == 0)
1788  {
1789  mutt_str_strfcpy(buf, C_SizeUnitsOnLeft ? "K0" : "0K", buflen);
1790  }
1791  else if (C_SizeShowFractions && (num < 10189)) /* 0.1K - 9.9K */
1792  {
1793  snprintf(buf, buflen, C_SizeUnitsOnLeft ? "K%3.1f" : "%3.1fK",
1794  (num < 103) ? 0.1 : (num / 1024.0));
1795  }
1796  else if (!C_SizeShowMb || (num < 1023949)) /* 10K - 999K */
1797  {
1798  /* 51 is magic which causes 10189/10240 to be rounded up to 10 */
1799  snprintf(buf, buflen, C_SizeUnitsOnLeft ? ("K%zu") : ("%zuK"), (num + 51) / 1024);
1800  }
1801  else if (C_SizeShowFractions && (num < 10433332)) /* 1.0M - 9.9M */
1802  {
1803  snprintf(buf, buflen, C_SizeUnitsOnLeft ? "M%3.1f" : "%3.1fM", num / 1048576.0);
1804  }
1805  else /* 10M+ */
1806  {
1807  /* (10433332 + 52428) / 1048576 = 10 */
1808  snprintf(buf, buflen, C_SizeUnitsOnLeft ? ("M%zu") : ("%zuM"), (num + 52428) / 1048576);
1809  }
1810 }
WHERE bool C_SizeShowFractions
Config: Show size fractions with a single decimal place.
Definition: globals.h:252
WHERE bool C_SizeShowMb
Config: Show sizes in megabytes for sizes greater than 1 megabyte.
Definition: globals.h:253
WHERE bool C_SizeUnitsOnLeft
Config: Show the units as a prefix to the size.
Definition: globals.h:254
WHERE bool C_SizeShowBytes
Config: Show smaller sizes in bytes.
Definition: globals.h:251
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 71 of file muttlib.c.