NeoMutt  2018-07-16 +2388-bcedc8
Teaching an old dog new tricks
DOXYGEN
muttlib.c File Reference

Some miscellaneous functions. More...

#include "config.h"
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <pwd.h>
#include <regex.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mutt/mutt.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "mutt.h"
#include "muttlib.h"
#include "alias.h"
#include "curs_lib.h"
#include "filter.h"
#include "format_flags.h"
#include "globals.h"
#include "hook.h"
#include "mutt_window.h"
#include "mx.h"
#include "ncrypt/ncrypt.h"
#include "protos.h"
#include "imap/imap.h"
+ Include dependency graph for muttlib.c:

Go to the source code of this file.

Functions

void mutt_adv_mktemp (struct Buffer *buf)
 Create a temporary file. More...
 
char * mutt_expand_path (char *buf, size_t buflen)
 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_expand_path (struct Buffer *buf)
 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...
 
bool mutt_needs_mailcap (struct Body *m)
 Does this type need a mailcap entry do display. More...
 
bool mutt_is_text_part (struct Body *b)
 Is this part of an email in plain text? More...
 
int mutt_randbuf (void *buf, size_t buflen)
 Fill a buffer with randomness. More...
 
void mutt_rand_base32 (void *buf, size_t buflen)
 Fill a buffer with a base32-encoded random string. 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_buffer_mktemp_full (struct Buffer *buf, const char *prefix, const char *suffix, const char *src, int line)
 Create a temporary file. More...
 
void mutt_mktemp_full (char *buf, size_t buflen, const char *prefix, const char *suffix, const char *src, int line)
 Create a temporary filename. More...
 
void mutt_pretty_mailbox (char *buf, size_t buflen)
 Shorten a mailbox path using '~' or '='. More...
 
void mutt_buffer_pretty_mailbox (struct Buffer *buf)
 Shorten a mailbox path using '~' or '='. More...
 
int mutt_check_overwrite (const char *attname, const char *path, char *fname, size_t flen, enum SaveAttach *opt, char **directory)
 Ask the user if overwriting is necessary. More...
 
void mutt_save_path (char *buf, size_t buflen, const struct Address *addr)
 Turn an email address into a filename (for saving) More...
 
void mutt_safe_path (char *buf, size_t buflen, const struct Address *a)
 Make a safe filename from an email address. 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...
 
FILE * mutt_open_read (const char *path, pid_t *thepid)
 Run a command to read from. More...
 
int mutt_save_confirm (const char *s, struct stat *st)
 Ask the user to save. More...
 
void mutt_sleep (short s)
 Sleep for a while. More...
 
const char * mutt_make_version (void)
 Generate the NeoMutt version string. More...
 
void mutt_encode_path (char *buf, size_t buflen, const char *src)
 Convert a path into the user's preferred character set. More...
 
int mutt_set_xdg_path (enum XdgType type, char *buf, size_t bufsize)
 Find an XDG path or its fallback. 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...
 
void mutt_buffer_sanitize_filename (struct Buffer *buf, const char *path, short slash)
 Replace unsafe characters in a filename. 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...
 
static const char * xdg_env_vars []
 
static const char * xdg_defaults []
 
static FILE * fp_random
 
static const unsigned char base32 [] = "abcdefghijklmnopqrstuvwxyz234567"
 

Detailed Description

Some miscellaneous functions.

Authors
  • Michael R. Elkins
  • Thomas Roessler
  • 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.c.

Function Documentation

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:75
#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:86
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:191
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:614
#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:314
char * data
Pointer to data.
Definition: buffer.h:35
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:52

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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:

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:76
struct AddressList * mutt_alias_lookup(const char *s)
Find an Alias.
Definition: alias.c:271
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:75
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2430
void mutt_buffer_increase_size(struct Buffer *buf, size_t new_size)
Increase the allocated size of a buffer.
Definition: buffer.c:339
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:724
String manipulation buffer.
Definition: buffer.h:33
WHERE char * LastFolder
Previously selected mailbox.
Definition: globals.h:54
WHERE char * C_Record
Config: Folder to save &#39;sent&#39; messages.
Definition: globals.h:138
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:191
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:2476
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:121
struct Envelope * env
Envelope information.
Definition: email.h:91
WHERE char * HomeDir
User&#39;s home directory.
Definition: globals.h:48
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: globals.h:53
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:41
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:212
int mutt_file_sanitize_regex(struct Buffer *dest, const char *src)
Escape any regex-magic characters in a string.
Definition: file.c:633
#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:314
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:123
#define PATH_MAX
Definition: mutt.h:51
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:151
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:1238
&#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:

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:

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:75
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
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:256
#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:

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:

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:

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:

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:

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:209
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:

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:209

+ Here is the call graph for this function:

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:209

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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:191
#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:52
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:49
#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:

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:52
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:49
#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:

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:48
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:123
#define PATH_MAX
Definition: mutt.h:51
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:689
Url is file://.
Definition: url.h:35

+ Here is the caller graph for this function:

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_buffer_increase_size(struct Buffer *buf, size_t new_size)
Increase the allocated size of a buffer.
Definition: buffer.c:339
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:212
#define PATH_MAX
Definition: mutt.h:51
char * data
Pointer to data.
Definition: buffer.h:35

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_check_overwrite ( const char *  attname,
const char *  path,
char *  fname,
size_t  flen,
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]flenLength of buffer
[out]optSave option, see SaveAttach
[out]directoryDirectory to save under (OPTIONAL)
Return values
0Success
-1Abort
1Error

Definition at line 711 of file muttlib.c.

713 {
714  struct stat st;
715 
716  mutt_str_strfcpy(fname, path, flen);
717  if (access(fname, F_OK) != 0)
718  return 0;
719  if (stat(fname, &st) != 0)
720  return -1;
721  if (S_ISDIR(st.st_mode))
722  {
723  enum QuadOption ans = MUTT_NO;
724  if (directory)
725  {
726  switch (mutt_multi_choice
727  /* L10N: Means "The path you specified as the destination file is a directory."
728  See the msgid "Save to file: " (alias.c, recvattach.c)
729  These three letters correspond to the choices in the string. */
730  (_("File is a directory, save under it: (y)es, (n)o, (a)ll?"), _("yna")))
731  {
732  case 3: /* all */
733  mutt_str_replace(directory, fname);
734  break;
735  case 1: /* yes */
736  FREE(directory);
737  break;
738  case -1: /* abort */
739  FREE(directory);
740  return -1;
741  case 2: /* no */
742  FREE(directory);
743  return 1;
744  }
745  }
746  /* L10N: Means "The path you specified as the destination file is a directory."
747  See the msgid "Save to file: " (alias.c, recvattach.c) */
748  else if ((ans = mutt_yesorno(_("File is a directory, save under it?"), MUTT_YES)) != MUTT_YES)
749  return (ans == MUTT_NO) ? 1 : -1;
750 
751  char tmp[PATH_MAX];
752  mutt_str_strfcpy(tmp, mutt_path_basename(NONULL(attname)), sizeof(tmp));
753  if ((mutt_get_field(_("File under directory: "), tmp, sizeof(tmp),
754  MUTT_FILE | MUTT_CLEAR) != 0) ||
755  !tmp[0])
756  {
757  return -1;
758  }
759  mutt_path_concat(fname, path, tmp, flen);
760  }
761 
762  if ((*opt == MUTT_SAVE_NO_FLAGS) && (access(fname, F_OK) == 0))
763  {
764  switch (
765  mutt_multi_choice(_("File exists, (o)verwrite, (a)ppend, or (c)ancel?"),
766  // L10N: Options for: File exists, (o)verwrite, (a)ppend, or (c)ancel?
767  _("oac")))
768  {
769  case -1: /* abort */
770  return -1;
771  case 3: /* cancel */
772  return 1;
773 
774  case 2: /* append */
775  *opt = MUTT_SAVE_APPEND;
776  break;
777  case 1: /* overwrite */
778  *opt = MUTT_SAVE_OVERWRITE;
779  break;
780  }
781  }
782  return 0;
783 }
char * mutt_path_concat(char *d, const char *dir, const char *fname, size_t l)
Join a directory name and a filename.
Definition: path.c:330
#define NONULL(x)
Definition: string2.h:37
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:69
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
No flags set.
Definition: mutt_attach.h:54
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
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
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:839
#define PATH_MAX
Definition: mutt.h:51
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
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
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:65
Append to existing file.
Definition: mutt_attach.h:55
#define FREE(x)
Definition: memory.h:40
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:

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

795 {
796  if (addr && addr->mailbox)
797  {
798  mutt_str_strfcpy(buf, addr->mailbox, buflen);
799  if (!C_SaveAddress)
800  {
801  char *p = strpbrk(buf, "%@");
802  if (p)
803  *p = '\0';
804  }
805  mutt_str_strlower(buf);
806  }
807  else
808  *buf = '\0';
809 }
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:259

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

820 {
821  mutt_save_path(buf, buflen, a);
822  for (char *p = buf; *p; p++)
823  if ((*p == '/') || IS_SPACE(*p) || !IsPrint((unsigned char) *p))
824  *p = '_';
825 }
#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:794

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1364 {
1365  FILE *fp = NULL;
1366  struct stat s;
1367 
1368  size_t len = mutt_str_strlen(path);
1369  if (len == 0)
1370  {
1371  return NULL;
1372  }
1373 
1374  if (path[len - 1] == '|')
1375  {
1376  /* read from a pipe */
1377 
1378  char *p = mutt_str_strdup(path);
1379 
1380  p[len - 1] = 0;
1381  mutt_endwin();
1382  *thepid = mutt_create_filter(p, NULL, &fp, NULL);
1383  FREE(&p);
1384  }
1385  else
1386  {
1387  if (stat(path, &s) < 0)
1388  return NULL;
1389  if (S_ISDIR(s.st_mode))
1390  {
1391  errno = EINVAL;
1392  return NULL;
1393  }
1394  fp = fopen(path, "r");
1395  *thepid = -1;
1396  }
1397  return fp;
1398 }
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:

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

1409 {
1410  char tmp[PATH_MAX];
1411  int ret = 0;
1412 
1413  enum MailboxType magic = mx_path_probe(s, NULL);
1414 
1415 #ifdef USE_POP
1416  if (magic == MUTT_POP)
1417  {
1418  mutt_error(_("Can't save message to POP mailbox"));
1419  return 1;
1420  }
1421 #endif
1422 
1423  if ((magic != MUTT_MAILBOX_ERROR) && (magic != MUTT_UNKNOWN) && !mx_access(s, W_OK))
1424  {
1425  if (C_Confirmappend)
1426  {
1427  snprintf(tmp, sizeof(tmp), _("Append messages to %s?"), s);
1428  enum QuadOption ans = mutt_yesorno(tmp, MUTT_YES);
1429  if (ans == MUTT_NO)
1430  ret = 1;
1431  else if (ans == MUTT_ABORT)
1432  ret = -1;
1433  }
1434  }
1435 
1436 #ifdef USE_NNTP
1437  if (magic == MUTT_NNTP)
1438  {
1439  mutt_error(_("Can't save message to news server"));
1440  return 0;
1441  }
1442 #endif
1443 
1444  if (stat(s, st) != -1)
1445  {
1446  if (magic == MUTT_MAILBOX_ERROR)
1447  {
1448  mutt_error(_("%s is not a mailbox"), s);
1449  return 1;
1450  }
1451  }
1452  else if (magic != MUTT_IMAP)
1453  {
1454  st->st_mtime = 0;
1455  st->st_atime = 0;
1456 
1457  /* pathname does not exist */
1458  if (errno == ENOENT)
1459  {
1460  if (C_Confirmcreate)
1461  {
1462  snprintf(tmp, sizeof(tmp), _("Create %s?"), s);
1463  enum QuadOption ans = mutt_yesorno(tmp, MUTT_YES);
1464  if (ans == MUTT_NO)
1465  ret = 1;
1466  else if (ans == MUTT_ABORT)
1467  ret = -1;
1468  }
1469 
1470  /* user confirmed with MUTT_YES or set C_Confirmcreate */
1471  if (ret == 0)
1472  {
1473  /* create dir recursively */
1474  char *tmp_path = mutt_path_dirname(s);
1475  if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
1476  {
1477  /* report failure & abort */
1478  mutt_perror(s);
1479  FREE(&tmp_path);
1480  return 1;
1481  }
1482  FREE(&tmp_path);
1483  }
1484  }
1485  else
1486  {
1487  mutt_perror(s);
1488  return 1;
1489  }
1490  }
1491 
1493  return ret;
1494 }
#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:218
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:219
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:872
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:51
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:1238
&#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:

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

1503 {
1504  if (C_SleepTime > s)
1505  sleep(C_SleepTime);
1506  else if (s)
1507  sleep(s);
1508 }
WHERE short C_SleepTime
Config: Time to pause after certain info messages.
Definition: globals.h:158

+ Here is the caller graph for this function:

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

1517 {
1518  static char vstring[256];
1519  snprintf(vstring, sizeof(vstring), "NeoMutt %s%s", PACKAGE_VERSION, GitVer);
1520  return vstring;
1521 }
const char * GitVer

+ Here is the caller graph for this function:

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

1532 {
1533  char *p = mutt_str_strdup(src);
1534  int rc = mutt_ch_convert_string(&p, C_Charset, "us-ascii", 0);
1535  /* 'src' may be NULL, such as when called from the pop3 driver. */
1536  size_t len = mutt_str_strfcpy(buf, (rc == 0) ? p : src, buflen);
1537 
1538  /* convert the path to POSIX "Portable Filename Character Set" */
1539  for (size_t i = 0; i < len; i++)
1540  {
1541  if (!isalnum(buf[i]) && !strchr("/.-_", buf[i]))
1542  {
1543  buf[i] = '_';
1544  }
1545  }
1546  FREE(&p);
1547 }
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:723
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:

int mutt_set_xdg_path ( enum XdgType  type,
char *  buf,
size_t  bufsize 
)

Find an XDG path or its fallback.

Parameters
typeType of XDG variable, e.g. XDG_CONFIG_HOME
bufBuffer to save path
bufsizeBuffer length
Return values
1if an entry was found that actually exists on disk and 0 otherwise

Process an XDG environment variable or its fallback.

Definition at line 1558 of file muttlib.c.

1559 {
1560  const char *xdg_env = mutt_str_getenv(xdg_env_vars[type]);
1561  char *xdg = xdg_env ? mutt_str_strdup(xdg_env) : mutt_str_strdup(xdg_defaults[type]);
1562  char *x = xdg; /* strsep() changes xdg, so free x instead later */
1563  char *token = NULL;
1564  int rc = 0;
1565 
1566  while ((token = strsep(&xdg, ":")))
1567  {
1568  if (snprintf(buf, bufsize, "%s/%s/neomuttrc", token, PACKAGE) < 0)
1569  continue;
1570  mutt_expand_path(buf, bufsize);
1571  if (access(buf, F_OK) == 0)
1572  {
1573  rc = 1;
1574  break;
1575  }
1576 
1577  if (snprintf(buf, bufsize, "%s/%s/Muttrc", token, PACKAGE) < 0)
1578  continue;
1579  mutt_expand_path(buf, bufsize);
1580  if (access(buf, F_OK) == 0)
1581  {
1582  rc = 1;
1583  break;
1584  }
1585  }
1586 
1587  FREE(&x);
1588  return rc;
1589 }
static const char * xdg_env_vars[]
Definition: muttlib.c:72
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1049
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:128
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
static const char * xdg_defaults[]
Definition: muttlib.c:77

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1598 {
1599  enum MailboxType mb_magic = mx_path_probe(path, NULL);
1600 
1601  if (mb_magic == MUTT_IMAP)
1602  imap_get_parent_path(path, buf, buflen);
1603  else if (mb_magic == MUTT_NOTMUCH)
1604  mutt_str_strfcpy(buf, C_Folder, buflen);
1605  else
1606  {
1607  mutt_str_strfcpy(buf, path, buflen);
1608  int n = mutt_str_strlen(buf);
1609  if (n == 0)
1610  return;
1611 
1612  /* remove any final trailing '/' */
1613  if (buf[n - 1] == '/')
1614  buf[n - 1] = '\0';
1615 
1616  /* Remove everything until the next slash */
1617  for (n--; ((n >= 0) && (buf[n] != '/')); n--)
1618  ;
1619 
1620  if (n > 0)
1621  buf[n] = '\0';
1622  else
1623  {
1624  buf[0] = '/';
1625  buf[1] = '\0';
1626  }
1627  }
1628 }
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
Definition: util.c:300
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:123
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:1238
&#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:

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

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

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

1699 {
1700  if (!buf || !path)
1701  return;
1702 
1703  mutt_buffer_reset(buf);
1704 
1705  for (; *path; path++)
1706  {
1707  if ((slash && (*path == '/')) || !strchr(filename_safe_chars, *path))
1708  mutt_buffer_addch(buf, '_');
1709  else
1710  mutt_buffer_addch(buf, *path);
1711  }
1712 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:76
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:271
const char filename_safe_chars[]
Definition: file.c:57

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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

struct Regex* C_GecosMask

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

Definition at line 70 of file muttlib.c.

const char* xdg_env_vars[]
static
Initial value:
= {
[XDG_CONFIG_HOME] = "XDG_CONFIG_HOME",
[XDG_CONFIG_DIRS] = "XDG_CONFIG_DIRS",
}
XDG home dir: ~/.config.
Definition: protos.h:47
XDG system dir: /etc/xdg.
Definition: protos.h:48

Definition at line 72 of file muttlib.c.

const char* xdg_defaults[]
static
Initial value:
= {
[XDG_CONFIG_HOME] = "~/.config",
[XDG_CONFIG_DIRS] = "/etc/xdg",
}
XDG home dir: ~/.config.
Definition: protos.h:47
XDG system dir: /etc/xdg.
Definition: protos.h:48

Definition at line 77 of file muttlib.c.

FILE* fp_random
static

Definition at line 459 of file muttlib.c.

const unsigned char base32[] = "abcdefghijklmnopqrstuvwxyz234567"
static

Definition at line 506 of file muttlib.c.