NeoMutt  2018-07-16 +2481-68dcde
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_RANDTAG_LEN   16
 
#define mutt_mktemp(buf, buflen)   mutt_mktemp_pfx_sfx(buf, buflen, "neomutt", NULL)
 
#define mutt_mktemp_pfx_sfx(buf, buflen, prefix, suffix)   mutt_mktemp_full(buf, buflen, prefix, suffix, __FILE__, __LINE__)
 
#define mutt_buffer_mktemp(buf)   mutt_buffer_mktemp_pfx_sfx(buf, "neomutt", NULL)
 
#define mutt_buffer_mktemp_pfx_sfx(buf, prefix, suffix)   mutt_buffer_mktemp_full(buf, prefix, suffix, __FILE__, __LINE__)
 

Functions

void mutt_adv_mktemp (struct Buffer *buf)
 Create a temporary file. More...
 
void mutt_buffer_mktemp_full (struct Buffer *buf, const char *prefix, const char *suffix, const char *src, int line)
 Create a temporary file. More...
 
void mutt_buffer_expand_path (struct Buffer *buf)
 Create the canonical path. More...
 
void mutt_buffer_expand_path_regex (struct Buffer *buf, bool regex)
 Create the canonical path (with regex char escaping) More...
 
void mutt_buffer_pretty_mailbox (struct Buffer *s)
 Shorten a mailbox path using '~' or '='. More...
 
void mutt_buffer_sanitize_filename (struct Buffer *buf, const char *path, short slash)
 Replace unsafe characters in a filename. More...
 
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...
 
bool mutt_matches_ignore (const char *s)
 Does the string match the ignore list. 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 (char *s, size_t l, 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_RANDTAG_LEN

#define MUTT_RANDTAG_LEN   16

Definition at line 43 of file muttlib.h.

◆ mutt_mktemp

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

Definition at line 76 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 77 of file muttlib.h.

◆ mutt_buffer_mktemp

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

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

91 {
92  if (!(buf->data && buf->data[0]))
93  {
94  mutt_buffer_mktemp(buf);
95  }
96  else
97  {
98  struct Buffer *prefix = mutt_buffer_pool_get();
99  mutt_buffer_strcpy(prefix, buf->data);
100  mutt_file_sanitize_filename(prefix->data, true);
101  mutt_buffer_printf(buf, "%s/%s", NONULL(C_Tmpdir), mutt_b2s(prefix));
102 
103  struct stat sb;
104  if ((lstat(mutt_b2s(buf), &sb) == -1) && (errno == ENOENT))
105  goto out;
106 
107  char *suffix = strchr(prefix->data, '.');
108  if (suffix)
109  {
110  *suffix = '\0';
111  suffix++;
112  }
113  mutt_buffer_mktemp_pfx_sfx(buf, prefix->data, suffix);
114 
115  out:
116  mutt_buffer_pool_release(&prefix);
117  }
118 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:79
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
#define mutt_buffer_mktemp_pfx_sfx(buf, prefix, suffix)
Definition: muttlib.h:80
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
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:613
#define mutt_b2s(buf)
Definition: buffer.h:41
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:310
char * data
Pointer to data.
Definition: buffer.h:35
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:53
+ 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 557 of file muttlib.c.

559 {
560  mutt_buffer_printf(buf, "%s/%s-%s-%d-%d-%" PRIu64 "%s%s", NONULL(C_Tmpdir),
561  NONULL(prefix), NONULL(ShortHostname), (int) getuid(),
562  (int) getpid(), mutt_rand64(), suffix ? "." : "", NONULL(suffix));
563 
564  mutt_debug(LL_DEBUG3, "%s:%d: mutt_mktemp returns \"%s\"\n", src, line, mutt_b2s(buf));
565  if (unlink(mutt_b2s(buf)) && (errno != ENOENT))
566  {
567  mutt_debug(LL_DEBUG1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src,
568  line, mutt_b2s(buf), strerror(errno), errno);
569  }
570 }
#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:540
Log at debug level 1.
Definition: logging.h:56
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:53
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:58
+ Here is the call graph for this function:

◆ mutt_buffer_expand_path()

void mutt_buffer_expand_path ( struct Buffer buf)

Create the canonical path.

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

Definition at line 323 of file muttlib.c.

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

141 {
142  const char *s = NULL;
143  const char *tail = "";
144 
145  bool recurse = false;
146 
147  struct Buffer *p = mutt_buffer_pool_get();
148  struct Buffer *q = mutt_buffer_pool_get();
149  struct Buffer *tmp = mutt_buffer_pool_get();
150 
151  do
152  {
153  recurse = false;
154  s = mutt_b2s(buf);
155 
156  switch (*s)
157  {
158  case '~':
159  {
160  if ((s[1] == '/') || (s[1] == '\0'))
161  {
163  tail = s + 1;
164  }
165  else
166  {
167  char *t = strchr(s + 1, '/');
168  if (t)
169  *t = '\0';
170 
171  struct passwd *pw = getpwnam(s + 1);
172  if (pw)
173  {
174  mutt_buffer_strcpy(p, pw->pw_dir);
175  if (t)
176  {
177  *t = '/';
178  tail = t;
179  }
180  else
181  tail = "";
182  }
183  else
184  {
185  /* user not found! */
186  if (t)
187  *t = '/';
189  tail = s;
190  }
191  }
192  break;
193  }
194 
195  case '=':
196  case '+':
197  {
198  enum MailboxType mb_type = mx_path_probe(C_Folder, NULL);
199 
200  /* if folder = {host} or imap[s]://host/: don't append slash */
201  if ((mb_type == MUTT_IMAP) && ((C_Folder[strlen(C_Folder) - 1] == '}') ||
202  (C_Folder[strlen(C_Folder) - 1] == '/')))
203  {
205  }
206  else if (mb_type == MUTT_NOTMUCH)
208  else if (C_Folder && (C_Folder[strlen(C_Folder) - 1] == '/'))
210  else
211  mutt_buffer_printf(p, "%s/", NONULL(C_Folder));
212 
213  tail = s + 1;
214  break;
215  }
216 
217  /* elm compatibility, @ expands alias to user name */
218 
219  case '@':
220  {
221  struct AddressList *al = mutt_alias_lookup(s + 1);
222  if (!TAILQ_EMPTY(al))
223  {
224  struct Email *e = email_new();
225  e->env = mutt_env_new();
226  mutt_addrlist_copy(&e->env->from, al, false);
227  mutt_addrlist_copy(&e->env->to, al, false);
228 
229  /* TODO: fix mutt_default_save() to use Buffer */
231  mutt_default_save(p->data, p->dsize, e);
233 
234  email_free(&e);
235  /* Avoid infinite recursion if the resulting folder starts with '@' */
236  if (*p->data != '@')
237  recurse = true;
238 
239  tail = "";
240  }
241  break;
242  }
243 
244  case '>':
245  {
247  tail = s + 1;
248  break;
249  }
250 
251  case '<':
252  {
254  tail = s + 1;
255  break;
256  }
257 
258  case '!':
259  {
260  if (s[1] == '!')
261  {
263  tail = s + 2;
264  }
265  else
266  {
268  tail = s + 1;
269  }
270  break;
271  }
272 
273  case '-':
274  {
276  tail = s + 1;
277  break;
278  }
279 
280  case '^':
281  {
283  tail = s + 1;
284  break;
285  }
286 
287  default:
288  {
290  tail = s;
291  }
292  }
293 
294  if (regex && *(mutt_b2s(p)) && !recurse)
295  {
297  mutt_buffer_printf(tmp, "%s%s", mutt_b2s(q), tail);
298  }
299  else
300  mutt_buffer_printf(tmp, "%s%s", mutt_b2s(p), tail);
301 
302  mutt_buffer_strcpy(buf, mutt_b2s(tmp));
303  } while (recurse);
304 
308 
309 #ifdef USE_IMAP
310  /* Rewrite IMAP path in canonical form - aids in string comparisons of
311  * folders. May possibly fail, in which case buf should be the same. */
312  if (imap_path_probe(mutt_b2s(buf), NULL) == MUTT_IMAP)
313  imap_expand_path(buf);
314 #endif
315 }
#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:286
The envelope/body of an email.
Definition: email.h:39
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2425
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
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:55
WHERE char * C_Record
Config: Folder to save &#39;sent&#39; messages.
Definition: globals.h:136
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:662
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:2471
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:122
struct Envelope * env
Envelope information.
Definition: email.h:91
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:632
#define mutt_b2s(buf)
Definition: buffer.h:41
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:310
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:124
#define PATH_MAX
Definition: mutt.h:52
char * data
Pointer to data.
Definition: buffer.h:35
&#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:149
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:1236
&#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 688 of file muttlib.c.

689 {
690  if (!buf || !buf->data)
691  return;
692  /* This reduces the size of the Buffer, so we can pass it through.
693  * We adjust the size just to make sure buf->data is not NULL though */
695  mutt_pretty_mailbox(buf->data, buf->dsize);
697 }
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:612
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:52
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 1705 of file muttlib.c.

1706 {
1707  if (!buf || !path)
1708  return;
1709 
1710  mutt_buffer_reset(buf);
1711 
1712  for (; *path; path++)
1713  {
1714  if ((slash && (*path == '/')) || !strchr(filename_safe_chars, *path))
1715  mutt_buffer_addch(buf, '_');
1716  else
1717  mutt_buffer_addch(buf, *path);
1718  }
1719 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
char * path
Path of Email (for local Mailboxes)
Definition: email.h:93
const char filename_safe_chars[]
Definition: file.c:58
+ 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 710 of file muttlib.c.

712 {
713  struct stat st;
714 
715  mutt_buffer_strcpy(fname, path);
716  if (access(mutt_b2s(fname), F_OK) != 0)
717  return 0;
718  if (stat(mutt_b2s(fname), &st) != 0)
719  return -1;
720  if (S_ISDIR(st.st_mode))
721  {
722  enum QuadOption ans = MUTT_NO;
723  if (directory)
724  {
725  switch (mutt_multi_choice
726  /* L10N: Means "The path you specified as the destination file is a directory."
727  See the msgid "Save to file: " (alias.c, recvattach.c)
728  These three letters correspond to the choices in the string. */
729  (_("File is a directory, save under it: (y)es, (n)o, (a)ll?"), _("yna")))
730  {
731  case 3: /* all */
732  mutt_str_replace(directory, mutt_b2s(fname));
733  break;
734  case 1: /* yes */
735  FREE(directory);
736  break;
737  case -1: /* abort */
738  FREE(directory);
739  return -1;
740  case 2: /* no */
741  FREE(directory);
742  return 1;
743  }
744  }
745  /* L10N: Means "The path you specified as the destination file is a directory."
746  See the msgid "Save to file: " (alias.c, recvattach.c) */
747  else if ((ans = mutt_yesorno(_("File is a directory, save under it?"), MUTT_YES)) != MUTT_YES)
748  return (ans == MUTT_NO) ? 1 : -1;
749 
750  struct Buffer *tmp = mutt_buffer_pool_get();
752  if (mutt_get_field(_("File under directory: "), tmp->data, tmp->dsize,
753  MUTT_FILE | MUTT_CLEAR) != 0)
754  {
756  return -1;
757  }
759  if (mutt_buffer_is_empty(tmp))
760  {
762  return (-1);
763  }
764  mutt_buffer_concat_path(fname, path, mutt_b2s(tmp));
766  }
767 
768  if ((*opt == MUTT_SAVE_NO_FLAGS) && (access(mutt_b2s(fname), F_OK) == 0))
769  {
770  switch (
771  mutt_multi_choice(_("File exists, (o)verwrite, (a)ppend, or (c)ancel?"),
772  // L10N: Options for: File exists, (o)verwrite, (a)ppend, or (c)ancel?
773  _("oac")))
774  {
775  case -1: /* abort */
776  return -1;
777  case 3: /* cancel */
778  return 1;
779 
780  case 2: /* append */
781  *opt = MUTT_SAVE_APPEND;
782  break;
783  case 1: /* overwrite */
784  *opt = MUTT_SAVE_OVERWRITE;
785  break;
786  }
787  }
788  return 0;
789 }
#define NONULL(x)
Definition: string2.h:37
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:70
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
No flags set.
Definition: mutt_attach.h:54
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
String manipulation buffer.
Definition: buffer.h:33
Overwrite existing file.
Definition: mutt_attach.h:56
#define _(a)
Definition: message.h:28
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
size_t dsize
Length of data.
Definition: buffer.h:37
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:332
const char * mutt_path_basename(const char *f)
Find the last component for a pathname.
Definition: path.c:307
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
#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:843
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:310
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
char * data
Pointer to data.
Definition: buffer.h:35
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:66
Append to existing file.
Definition: mutt_attach.h:55
#define FREE(x)
Definition: memory.h:40
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
void mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:352
+ 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 1538 of file muttlib.c.

1539 {
1540  char *p = mutt_str_strdup(src);
1541  int rc = mutt_ch_convert_string(&p, C_Charset, "us-ascii", 0);
1542  /* 'src' may be NULL, such as when called from the pop3 driver. */
1543  size_t len = mutt_str_strfcpy(buf, (rc == 0) ? p : src, buflen);
1544 
1545  /* convert the path to POSIX "Portable Filename Character Set" */
1546  for (size_t i = 0; i < len; i++)
1547  {
1548  if (!isalnum(buf[i]) && !strchr("/.-_", buf[i]))
1549  {
1550  buf[i] = '_';
1551  }
1552  }
1553  FREE(&p);
1554 }
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 844 of file muttlib.c.

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

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

338 {
339  struct Buffer *tmp = mutt_buffer_pool_get();
340 
341  mutt_buffer_addstr(tmp, NONULL(buf));
342  mutt_buffer_expand_path_regex(tmp, regex);
343  mutt_str_strfcpy(buf, mutt_b2s(tmp), buflen);
344 
346 
347  return buf;
348 }
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:100
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:111
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:140
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 362 of file muttlib.c.

363 {
364  regmatch_t pat_match[1];
365  size_t pwnl;
366  char *p = NULL;
367 
368  if (!pw || !pw->pw_gecos)
369  return NULL;
370 
371  memset(dest, 0, destlen);
372 
373  if (mutt_regex_capture(C_GecosMask, pw->pw_gecos, 1, pat_match))
374  {
375  mutt_str_strfcpy(dest, pw->pw_gecos + pat_match[0].rm_so,
376  MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
377  }
378  else if ((p = strchr(pw->pw_gecos, ',')))
379  mutt_str_strfcpy(dest, pw->pw_gecos, MIN(destlen, p - pw->pw_gecos + 1));
380  else
381  mutt_str_strfcpy(dest, pw->pw_gecos, destlen);
382 
383  pwnl = strlen(pw->pw_name);
384 
385  for (int idx = 0; dest[idx]; idx++)
386  {
387  if (dest[idx] == '&')
388  {
389  memmove(&dest[idx + pwnl], &dest[idx + 1],
390  MAX((ssize_t)(destlen - idx - pwnl - 1), 0));
391  memcpy(&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl));
392  dest[idx] = toupper((unsigned char) dest[idx]);
393  }
394  }
395 
396  return dest;
397 }
#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:70
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 1604 of file muttlib.c.

1605 {
1606  enum MailboxType mb_magic = mx_path_probe(path, NULL);
1607 
1608  if (mb_magic == MUTT_IMAP)
1609  imap_get_parent_path(path, buf, buflen);
1610  else if (mb_magic == MUTT_NOTMUCH)
1611  mutt_str_strfcpy(buf, C_Folder, buflen);
1612  else
1613  {
1614  mutt_str_strfcpy(buf, path, buflen);
1615  int n = mutt_str_strlen(buf);
1616  if (n == 0)
1617  return;
1618 
1619  /* remove any final trailing '/' */
1620  if (buf[n - 1] == '/')
1621  buf[n - 1] = '\0';
1622 
1623  /* Remove everything until the next slash */
1624  for (n--; ((n >= 0) && (buf[n] != '/')); n--)
1625  ;
1626 
1627  if (n > 0)
1628  buf[n] = '\0';
1629  else
1630  {
1631  buf[0] = '/';
1632  buf[1] = '\0';
1633  }
1634  }
1635 }
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:299
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:124
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:1236
&#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 1659 of file muttlib.c.

1660 {
1661  /* fast-track in case the paths have been mutt_pretty_mailbox'ified */
1662  if ((a[0] == '+') && (b[0] == '+'))
1663  {
1664  return (mutt_str_strcasecmp(a + 1, "inbox") == 0) ?
1665  -1 :
1666  (mutt_str_strcasecmp(b + 1, "inbox") == 0) ? 1 : 0;
1667  }
1668 
1669  const char *a_end = strrchr(a, '/');
1670  const char *b_end = strrchr(b, '/');
1671 
1672  /* If one path contains a '/', but not the other */
1673  if ((!a_end) ^ (!b_end))
1674  return 0;
1675 
1676  /* If neither path contains a '/' */
1677  if (!a_end)
1678  return 0;
1679 
1680  /* Compare the subpaths */
1681  size_t a_len = a_end - a;
1682  size_t b_len = b_end - b;
1683  size_t min = MIN(a_len, b_len);
1684  int same = (a[min] == '/') && (b[min] == '/') && (a[min + 1] != '\0') &&
1685  (b[min + 1] != '\0') && (mutt_str_strncasecmp(a, b, min) == 0);
1686 
1687  if (!same)
1688  return 0;
1689 
1690  if (mutt_str_strcasecmp(&a[min + 1], "inbox") == 0)
1691  return -1;
1692 
1693  if (mutt_str_strcasecmp(&b[min + 1], "inbox") == 0)
1694  return 1;
1695 
1696  return 0;
1697 }
#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 433 of file muttlib.c.

434 {
435  int t = b->type;
436  char *s = b->subtype;
437 
439  return false;
440 
441  if (t == TYPE_TEXT)
442  return true;
443 
444  if (t == TYPE_MESSAGE)
445  {
446  if (mutt_str_strcasecmp("delivery-status", s) == 0)
447  return true;
448  }
449 
450  if (((WithCrypto & APPLICATION_PGP) != 0) && (t == TYPE_APPLICATION))
451  {
452  if (mutt_str_strcasecmp("pgp-keys", s) == 0)
453  return true;
454  }
455 
456  return false;
457 }
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:560
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 1523 of file muttlib.c.

1524 {
1525  static char vstring[256];
1526  snprintf(vstring, sizeof(vstring), "NeoMutt %s%s", PACKAGE_VERSION, GitVer);
1527  return vstring;
1528 }
const char * GitVer

◆ mutt_matches_ignore()

bool mutt_matches_ignore ( const char *  s)

Does the string match the ignore list.

Parameters
sString to check
Return values
trueIf string matches

Checks Ignore and UnIgnore using mutt_list_match

Definition at line 307 of file parse.c.

308 {
309  return mutt_list_match(s, &Ignore) && !mutt_list_match(s, &UnIgnore);
310 }
bool mutt_list_match(const char *s, struct ListHead *h)
Is the string in the list (see notes)
Definition: list.c:196
struct ListHead UnIgnore
List of header patterns to unignore (see)
Definition: email_globals.c:46
struct ListHead Ignore
List of header patterns to ignore.
Definition: email_globals.c:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_mktemp_full()

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

Create a temporary filename.

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

Definition at line 583 of file muttlib.c.

585 {
586  size_t n =
587  snprintf(buf, buflen, "%s/%s-%s-%d-%d-%" PRIu64 "%s%s", NONULL(C_Tmpdir),
588  NONULL(prefix), NONULL(ShortHostname), (int) getuid(),
589  (int) getpid(), mutt_rand64(), suffix ? "." : "", NONULL(suffix));
590  if (n >= buflen)
591  {
593  "%s:%d: ERROR: insufficient buffer space to hold temporary "
594  "filename! buflen=%zu but need %zu\n",
595  src, line, buflen, n);
596  }
597  mutt_debug(LL_DEBUG3, "%s:%d: mutt_mktemp returns \"%s\"\n", src, line, buf);
598  if (unlink(buf) && (errno != ENOENT))
599  {
600  mutt_debug(LL_DEBUG1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src,
601  line, buf, strerror(errno), errno);
602  }
603 }
#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:540
Log at debug level 1.
Definition: logging.h:56
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:53
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:58
+ 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 405 of file muttlib.c.

406 {
407  switch (m->type)
408  {
409  case TYPE_TEXT:
410  if (mutt_str_strcasecmp("plain", m->subtype) == 0)
411  return false;
412  break;
413  case TYPE_APPLICATION:
415  return false;
417  return false;
418  break;
419 
420  case TYPE_MULTIPART:
421  case TYPE_MESSAGE:
422  return false;
423  }
424 
425  return true;
426 }
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:560
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:619
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 1370 of file muttlib.c.

1371 {
1372  FILE *fp = NULL;
1373  struct stat s;
1374 
1375  size_t len = mutt_str_strlen(path);
1376  if (len == 0)
1377  {
1378  return NULL;
1379  }
1380 
1381  if (path[len - 1] == '|')
1382  {
1383  /* read from a pipe */
1384 
1385  char *p = mutt_str_strdup(path);
1386 
1387  p[len - 1] = 0;
1388  mutt_endwin();
1389  *thepid = mutt_create_filter(p, NULL, &fp, NULL);
1390  FREE(&p);
1391  }
1392  else
1393  {
1394  if (stat(path, &s) < 0)
1395  return NULL;
1396  if (S_ISDIR(s.st_mode))
1397  {
1398  errno = EINVAL;
1399  return NULL;
1400  }
1401  fp = fopen(path, "r");
1402  *thepid = -1;
1403  }
1404  return fp;
1405 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:217
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:499
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 612 of file muttlib.c.

613 {
614  if (!buf)
615  return;
616 
617  char *p = buf, *q = buf;
618  size_t len;
619  enum UrlScheme scheme;
620  char tmp[PATH_MAX];
621 
622  scheme = url_check_scheme(buf);
623 
624  if ((scheme == U_IMAP) || (scheme == U_IMAPS))
625  {
626  imap_pretty_mailbox(buf, buflen, C_Folder);
627  return;
628  }
629 
630  if (scheme == U_NOTMUCH)
631  return;
632 
633  /* if buf is an url, only collapse path component */
634  if (scheme != U_UNKNOWN)
635  {
636  p = strchr(buf, ':') + 1;
637  if (strncmp(p, "//", 2) == 0)
638  q = strchr(p + 2, '/');
639  if (!q)
640  q = strchr(p, '\0');
641  p = q;
642  }
643 
644  /* cleanup path */
645  if (strstr(p, "//") || strstr(p, "/./"))
646  {
647  /* first attempt to collapse the pathname, this is more
648  * lightweight than realpath() and doesn't resolve links */
649  while (*p)
650  {
651  if ((p[0] == '/') && (p[1] == '/'))
652  {
653  *q++ = '/';
654  p += 2;
655  }
656  else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
657  {
658  *q++ = '/';
659  p += 3;
660  }
661  else
662  *q++ = *p++;
663  }
664  *q = '\0';
665  }
666  else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
667  realpath(p, tmp))
668  {
669  mutt_str_strfcpy(p, tmp, buflen - (p - buf));
670  }
671 
672  if ((len = mutt_str_startswith(buf, C_Folder, CASE_MATCH)) && (buf[len] == '/'))
673  {
674  *buf++ = '=';
675  memmove(buf, buf + len, mutt_str_strlen(buf + len) + 1);
676  }
677  else if ((len = mutt_str_startswith(buf, HomeDir, CASE_MATCH)) && (buf[len] == '/'))
678  {
679  *buf++ = '~';
680  memmove(buf, buf + len - 1, mutt_str_strlen(buf + len - 1) + 1);
681  }
682 }
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:124
#define PATH_MAX
Definition: mutt.h:52
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:688
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 527 of file muttlib.c.

528 {
529  uint32_t num = 0;
530 
531  if (mutt_randbuf(&num, sizeof(num)) < 0)
532  mutt_exit(1);
533  return num;
534 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:468
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 540 of file muttlib.c.

541 {
542  uint64_t num = 0;
543 
544  if (mutt_randbuf(&num, sizeof(num)) < 0)
545  mutt_exit(1);
546  return num;
547 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:468
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 513 of file muttlib.c.

514 {
515  uint8_t *p = buf;
516 
517  if (mutt_randbuf(p, buflen) < 0)
518  mutt_exit(1);
519  for (size_t pos = 0; pos < buflen; pos++)
520  p[pos] = base32[p[pos] % 32];
521 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:468
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:210
static const unsigned char base32[]
Definition: muttlib.c:506
+ 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 468 of file muttlib.c.

469 {
470  if (buflen > 1048576)
471  {
472  mutt_error(_("mutt_randbuf buflen=%zu"), buflen);
473  return -1;
474  }
475 /* XXX switch to HAVE_GETRANDOM and getrandom() in about 2017 */
476 #if defined(SYS_getrandom) && defined(__linux__)
477  long ret;
478  do
479  {
480  ret = syscall(SYS_getrandom, buf, buflen, 0, 0, 0, 0);
481  } while ((ret == -1) && (errno == EINTR));
482  if (ret == buflen)
483  return 0;
484 #endif
485  /* let's try urandom in case we're on an old kernel, or the user has
486  * configured selinux, seccomp or something to not allow getrandom */
487  if (!fp_random)
488  {
489  fp_random = fopen("/dev/urandom", "rb");
490  if (!fp_random)
491  {
492  mutt_error(_("open /dev/urandom: %s"), strerror(errno));
493  return -1;
494  }
495  setbuf(fp_random, NULL);
496  }
497  if (fread(buf, 1, buflen, fp_random) != buflen)
498  {
499  mutt_error(_("read /dev/urandom: %s"), strerror(errno));
500  return -1;
501  }
502 
503  return 0;
504 }
#define _(a)
Definition: message.h:28
static FILE * fp_random
Definition: muttlib.c:459
#define mutt_error(...)
Definition: logging.h:84
+ Here is the caller graph for this function:

◆ mutt_safe_path()

void mutt_safe_path ( char *  buf,
size_t  buflen,
const struct Address a 
)

Make a safe filename from an email address.

Parameters
bufBuffer for the result
buflenLength of buffer
aAddress to use

The filename will be stripped of '/', space, etc to make it safe.

Definition at line 825 of file muttlib.c.

826 {
827  mutt_save_path(buf, buflen, a);
828  for (char *p = buf; *p; p++)
829  if ((*p == '/') || IS_SPACE(*p) || !IsPrint((unsigned char) *p))
830  *p = '_';
831 }
#define IsPrint(ch)
Definition: mbyte.h:38
#define IS_SPACE(ch)
Definition: string2.h:38
void mutt_save_path(char *buf, size_t buflen, const struct Address *addr)
Turn an email address into a filename (for saving)
Definition: muttlib.c:800
+ 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 1415 of file muttlib.c.

1416 {
1417  char tmp[PATH_MAX];
1418  int ret = 0;
1419 
1420  enum MailboxType magic = mx_path_probe(s, NULL);
1421 
1422 #ifdef USE_POP
1423  if (magic == MUTT_POP)
1424  {
1425  mutt_error(_("Can't save message to POP mailbox"));
1426  return 1;
1427  }
1428 #endif
1429 
1430  if ((magic != MUTT_MAILBOX_ERROR) && (magic != MUTT_UNKNOWN) && !mx_access(s, W_OK))
1431  {
1432  if (C_Confirmappend)
1433  {
1434  snprintf(tmp, sizeof(tmp), _("Append messages to %s?"), s);
1435  enum QuadOption ans = mutt_yesorno(tmp, MUTT_YES);
1436  if (ans == MUTT_NO)
1437  ret = 1;
1438  else if (ans == MUTT_ABORT)
1439  ret = -1;
1440  }
1441  }
1442 
1443 #ifdef USE_NNTP
1444  if (magic == MUTT_NNTP)
1445  {
1446  mutt_error(_("Can't save message to news server"));
1447  return 0;
1448  }
1449 #endif
1450 
1451  if (stat(s, st) != -1)
1452  {
1453  if (magic == MUTT_MAILBOX_ERROR)
1454  {
1455  mutt_error(_("%s is not a mailbox"), s);
1456  return 1;
1457  }
1458  }
1459  else if (magic != MUTT_IMAP)
1460  {
1461  st->st_mtime = 0;
1462  st->st_atime = 0;
1463 
1464  /* pathname does not exist */
1465  if (errno == ENOENT)
1466  {
1467  if (C_Confirmcreate)
1468  {
1469  snprintf(tmp, sizeof(tmp), _("Create %s?"), s);
1470  enum QuadOption ans = mutt_yesorno(tmp, MUTT_YES);
1471  if (ans == MUTT_NO)
1472  ret = 1;
1473  else if (ans == MUTT_ABORT)
1474  ret = -1;
1475  }
1476 
1477  /* user confirmed with MUTT_YES or set C_Confirmcreate */
1478  if (ret == 0)
1479  {
1480  /* create dir recursively */
1481  char *tmp_path = mutt_path_dirname(s);
1482  if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
1483  {
1484  /* report failure & abort */
1485  mutt_perror(s);
1486  FREE(&tmp_path);
1487  return 1;
1488  }
1489  FREE(&tmp_path);
1490  }
1491  }
1492  else
1493  {
1494  mutt_perror(s);
1495  return 1;
1496  }
1497  }
1498 
1500  return ret;
1501 }
#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:214
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:412
#define _(a)
Definition: message.h:28
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:46
Error occurred examining Mailbox.
Definition: mailbox.h:45
WHERE bool C_Confirmcreate
Config: Confirm before creating a new mailbox.
Definition: globals.h:215
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:332
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:871
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:95
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:54
#define PATH_MAX
Definition: mutt.h:52
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:170
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:1236
&#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 800 of file muttlib.c.

801 {
802  if (addr && addr->mailbox)
803  {
804  mutt_str_strfcpy(buf, addr->mailbox, buflen);
805  if (!C_SaveAddress)
806  {
807  char *p = strpbrk(buf, "%@");
808  if (p)
809  *p = '\0';
810  }
811  mutt_str_strlower(buf);
812  }
813  else
814  *buf = '\0';
815 }
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:255
+ 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 1509 of file muttlib.c.

1510 {
1511  if (C_SleepTime > s)
1512  sleep(C_SleepTime);
1513  else if (s)
1514  sleep(s);
1515 }
WHERE short C_SleepTime
Config: Time to pause after certain info messages.
Definition: globals.h:155
+ 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 1727 of file muttlib.c.

1728 {
1729  if (!buf || (buflen == 0))
1730  return;
1731 
1732  if (C_SizeShowBytes && (num < 1024))
1733  {
1734  snprintf(buf, buflen, "%d", (int) num);
1735  }
1736  else if (num == 0)
1737  {
1738  mutt_str_strfcpy(buf, C_SizeUnitsOnLeft ? "K0" : "0K", buflen);
1739  }
1740  else if (C_SizeShowFractions && (num < 10189)) /* 0.1K - 9.9K */
1741  {
1742  snprintf(buf, buflen, C_SizeUnitsOnLeft ? "K%3.1f" : "%3.1fK",
1743  (num < 103) ? 0.1 : (num / 1024.0));
1744  }
1745  else if (!C_SizeShowMb || (num < 1023949)) /* 10K - 999K */
1746  {
1747  /* 51 is magic which causes 10189/10240 to be rounded up to 10 */
1748  snprintf(buf, buflen, C_SizeUnitsOnLeft ? ("K%zu") : ("%zuK"), (num + 51) / 1024);
1749  }
1750  else if (C_SizeShowFractions && (num < 10433332)) /* 1.0M - 9.9M */
1751  {
1752  snprintf(buf, buflen, C_SizeUnitsOnLeft ? "M%3.1f" : "%3.1fM", num / 1048576.0);
1753  }
1754  else /* 10M+ */
1755  {
1756  /* (10433332 + 52428) / 1048576 = 10 */
1757  snprintf(buf, buflen, C_SizeUnitsOnLeft ? ("M%zu") : ("%zuM"), (num + 52428) / 1048576);
1758  }
1759 }
WHERE bool C_SizeShowFractions
Config: Show size fractions with a single decimal place.
Definition: globals.h:263
WHERE bool C_SizeShowMb
Config: Show sizes in megabytes for sizes greater than 1 megabyte.
Definition: globals.h:264
WHERE bool C_SizeUnitsOnLeft
Config: Show the units as a prefix to the size.
Definition: globals.h:265
WHERE bool C_SizeShowBytes
Config: Show smaller sizes in bytes.
Definition: globals.h:262
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 70 of file muttlib.c.