NeoMutt  2018-07-16 +952-a2da0a
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 "config/lib.h"
#include "email/lib.h"
#include "conn/conn.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_buffer_adv_mktemp (struct Buffer *buf)
 Create a temporary file. More...
 
void mutt_adv_mktemp (char *buf, size_t buflen)
 Advanced mktemp(3) More...
 
char * mutt_expand_path (char *buf, size_t buflen)
 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...
 
int mutt_check_overwrite (const char *attname, const char *path, char *fname, size_t flen, int *append, char **directory)
 Ask the user if overwriting is necessary. More...
 
void mutt_save_path (char *buf, size_t buflen, struct Address *addr)
 Turn an email address into a filename (for saving) More...
 
void mutt_safe_path (char *buf, size_t buflen, 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, enum FormatFlag 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 (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...
 

Variables

struct RegexGecosMask
 Config: Regex for parsing GECOS field of /etc/passwd. More...
 
static const char * xdg_env_vars []
 
static const char * xdg_defaults []
 
static FILE * frandom
 
static const unsigned char base32 [] = "abcdefghijklmnopqrstuvwxyz234567"
 

Detailed Description

Some miscellaneous functions.

Authors
  • Michael R. Elkins
  • Thomas Roessler

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_buffer_adv_mktemp ( struct Buffer buf)

Create a temporary file.

Parameters
bufBuffer for the name

Definition at line 84 of file muttlib.c.

85 {
86  if (!(buf->data && buf->data[0]))
87  {
88  mutt_buffer_mktemp(buf);
89  }
90  else
91  {
92  struct Buffer *prefix = mutt_buffer_pool_get();
93  mutt_buffer_strcpy(prefix, buf->data);
95  mutt_buffer_printf(buf, "%s/%s", NONULL(Tmpdir), mutt_b2s(prefix));
96 
97  struct stat sb;
98  if (lstat(mutt_b2s(buf), &sb) == -1 && errno == ENOENT)
99  goto out;
100 
101  char *suffix = strrchr(prefix->data, '.');
102  if (suffix)
103  {
104  *suffix = 0;
105  suffix++;
106  }
107  mutt_buffer_mktemp_pfx_sfx(buf, mutt_b2s(prefix), suffix);
108 
109  out:
110  mutt_buffer_pool_release(&prefix);
111  }
112 }
#define NONULL(x)
Definition: string2.h:39
String manipulation buffer.
Definition: buffer.h:33
#define mutt_buffer_mktemp(a)
Definition: muttlib.h:74
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:200
#define mutt_buffer_mktemp_pfx_sfx(a, b, c)
Definition: muttlib.h:75
void mutt_file_sanitize_filename(char *f, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:578
#define mutt_b2s(buf)
Definition: buffer.h:42
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:316
char * data
pointer to data
Definition: buffer.h:35
char * Tmpdir
Config: Directory for temporary files.
Definition: file.c:50
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: buffer.c:396
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: buffer.c:385

+ Here is the call graph for this function:

void mutt_adv_mktemp ( char *  buf,
size_t  buflen 
)

Advanced mktemp(3)

Parameters
bufBuffer for result
buflenLength of buffer

Modified by blong to 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 123 of file muttlib.c.

124 {
125  if (buf[0] == '\0')
126  {
127  mutt_mktemp(buf, buflen);
128  }
129  else
130  {
131  char prefix[PATH_MAX];
132  mutt_str_strfcpy(prefix, buf, sizeof(prefix));
133  mutt_file_sanitize_filename(prefix, true);
134  snprintf(buf, buflen, "%s/%s", NONULL(Tmpdir), prefix);
135  struct stat sb;
136  if (lstat(buf, &sb) == -1 && errno == ENOENT)
137  return;
138 
139  char *suffix = strrchr(prefix, '.');
140  if (suffix)
141  {
142  *suffix = 0;
143  suffix++;
144  }
145  mutt_mktemp_pfx_sfx(buf, buflen, prefix, suffix);
146  }
147 }
#define NONULL(x)
Definition: string2.h:39
void mutt_file_sanitize_filename(char *f, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:578
#define mutt_mktemp(a, b)
Definition: muttlib.h:71
#define PATH_MAX
Definition: mutt.h:46
#define mutt_mktemp_pfx_sfx(a, b, c, d)
Definition: muttlib.h:72
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:742
char * Tmpdir
Config: Directory for temporary files.
Definition: file.c:50

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

158 {
159  return mutt_expand_path_regex(buf, buflen, false);
160 }
char * mutt_expand_path_regex(char *buf, size_t buflen, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:171

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

172 {
173  char p[PATH_MAX] = "";
174  char q[PATH_MAX] = "";
175  char tmp[PATH_MAX];
176  char *t = NULL;
177 
178  const char *tail = "";
179 
180  bool recurse = false;
181 
182  do
183  {
184  recurse = false;
185 
186  switch (*buf)
187  {
188  case '~':
189  {
190  if (*(buf + 1) == '/' || *(buf + 1) == 0)
191  {
192  mutt_str_strfcpy(p, HomeDir, sizeof(p));
193  tail = buf + 1;
194  }
195  else
196  {
197  struct passwd *pw = NULL;
198  t = strchr(buf + 1, '/');
199  if (t)
200  *t = 0;
201 
202  pw = getpwnam(buf + 1);
203  if (pw)
204  {
205  mutt_str_strfcpy(p, pw->pw_dir, sizeof(p));
206  if (t)
207  {
208  *t = '/';
209  tail = t;
210  }
211  else
212  tail = "";
213  }
214  else
215  {
216  /* user not found! */
217  if (t)
218  *t = '/';
219  *p = '\0';
220  tail = buf;
221  }
222  }
223  }
224  break;
225 
226  case '=':
227  case '+':
228  {
229  enum MailboxType mb_type = mx_path_probe(Folder, NULL);
230 
231  /* if folder = {host} or imap[s]://host/: don't append slash */
232  if ((mb_type == MUTT_IMAP) &&
233  (Folder[strlen(Folder) - 1] == '}' || Folder[strlen(Folder) - 1] == '/'))
234  {
235  mutt_str_strfcpy(p, Folder, sizeof(p));
236  }
237  else if (mb_type == MUTT_NOTMUCH)
238  mutt_str_strfcpy(p, Folder, sizeof(p));
239  else if (Folder && *Folder && Folder[strlen(Folder) - 1] == '/')
240  mutt_str_strfcpy(p, Folder, sizeof(p));
241  else
242  snprintf(p, sizeof(p), "%s/", NONULL(Folder));
243 
244  tail = buf + 1;
245  }
246  break;
247 
248  /* elm compatibility, @ expands alias to user name */
249 
250  case '@':
251  {
252  struct Address *alias = mutt_alias_lookup(buf + 1);
253  if (alias)
254  {
255  struct Email *e = mutt_email_new();
256  e->env = mutt_env_new();
257  e->env->from = alias;
258  e->env->to = alias;
259  mutt_default_save(p, sizeof(p), e);
260  e->env->from = NULL;
261  e->env->to = NULL;
262  mutt_email_free(&e);
263  /* Avoid infinite recursion if the resulting folder starts with '@' */
264  if (*p != '@')
265  recurse = true;
266 
267  tail = "";
268  }
269  }
270  break;
271 
272  case '>':
273  {
274  mutt_str_strfcpy(p, Mbox, sizeof(p));
275  tail = buf + 1;
276  }
277  break;
278 
279  case '<':
280  {
281  mutt_str_strfcpy(p, Record, sizeof(p));
282  tail = buf + 1;
283  }
284  break;
285 
286  case '!':
287  {
288  if (*(buf + 1) == '!')
289  {
290  mutt_str_strfcpy(p, LastFolder, sizeof(p));
291  tail = buf + 2;
292  }
293  else
294  {
295  mutt_str_strfcpy(p, Spoolfile, sizeof(p));
296  tail = buf + 1;
297  }
298  }
299  break;
300 
301  case '-':
302  {
303  mutt_str_strfcpy(p, LastFolder, sizeof(p));
304  tail = buf + 1;
305  }
306  break;
307 
308  case '^':
309  {
310  mutt_str_strfcpy(p, CurrentFolder, sizeof(p));
311  tail = buf + 1;
312  }
313  break;
314 
315  default:
316  {
317  *p = '\0';
318  tail = buf;
319  }
320  }
321 
322  if (regex && *p && !recurse)
323  {
324  mutt_file_sanitize_regex(q, sizeof(q), p);
325  snprintf(tmp, sizeof(tmp), "%s%s", q, tail);
326  }
327  else
328  snprintf(tmp, sizeof(tmp), "%s%s", p, tail);
329 
330  mutt_str_strfcpy(buf, tmp, buflen);
331  } while (recurse);
332 
333 #ifdef USE_IMAP
334  /* Rewrite IMAP path in canonical form - aids in string comparisons of
335  * folders. May possibly fail, in which case buf should be the same. */
336  if (imap_path_probe(buf, NULL) == MUTT_IMAP)
337  imap_path_canon(buf, buflen);
338 #endif
339 
340  return buf;
341 }
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: magic.h:43
#define NONULL(x)
Definition: string2.h:39
The envelope/body of an email.
Definition: email.h:35
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2479
struct Address * to
Definition: envelope.h:36
An email address.
Definition: address.h:32
WHERE char * LastFolder
Previously selected mailbox.
Definition: globals.h:53
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
struct Email * mutt_email_new(void)
Create a new Email.
Definition: email.c:63
struct Address * mutt_alias_lookup(const char *s)
Find an Alias.
Definition: alias.c:277
void mutt_default_save(char *path, size_t pathlen, struct Email *e)
Find the default save path for an email.
Definition: hook.c:523
int mutt_file_sanitize_regex(char *dest, size_t destlen, const char *src)
Escape any regex-magic characters in a string.
Definition: file.c:598
struct Envelope * env
envelope information
Definition: email.h:91
WHERE char * HomeDir
User&#39;s home directory.
Definition: globals.h:47
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: globals.h:52
struct Address * from
Definition: envelope.h:35
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:40
WHERE char * Mbox
Config: Folder that receives read emails (see Move)
Definition: globals.h:117
A folder/dir in the browser.
Definition: browser.h:47
#define PATH_MAX
Definition: mutt.h:46
MailboxType
Supported mailbox formats.
Definition: magic.h:33
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:742
WHERE char * Record
Config: Folder to save &#39;sent&#39; messages.
Definition: globals.h:134
void mutt_email_free(struct Email **e)
Free an Email.
Definition: email.c:41
int imap_path_canon(char *buf, size_t buflen)
Canonicalise a mailbox path - Implements MxOps::path_canon()
Definition: imap.c:2496
WHERE char * Spoolfile
Config: Inbox.
Definition: globals.h:147
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1438

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

356 {
357  regmatch_t pat_match[1];
358  size_t pwnl;
359  char *p = NULL;
360 
361  if (!pw || !pw->pw_gecos)
362  return NULL;
363 
364  memset(dest, 0, destlen);
365 
366  if (GecosMask && GecosMask->regex)
367  {
368  if (regexec(GecosMask->regex, pw->pw_gecos, 1, pat_match, 0) == 0)
369  {
370  mutt_str_strfcpy(dest, pw->pw_gecos + pat_match[0].rm_so,
371  MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
372  }
373  }
374  else if ((p = strchr(pw->pw_gecos, ',')))
375  mutt_str_strfcpy(dest, pw->pw_gecos, MIN(destlen, p - pw->pw_gecos + 1));
376  else
377  mutt_str_strfcpy(dest, pw->pw_gecos, destlen);
378 
379  pwnl = strlen(pw->pw_name);
380 
381  for (int idx = 0; dest[idx]; idx++)
382  {
383  if (dest[idx] == '&')
384  {
385  memmove(&dest[idx + pwnl], &dest[idx + 1],
386  MAX((ssize_t)(destlen - idx - pwnl - 1), 0));
387  memcpy(&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl));
388  dest[idx] = toupper((unsigned char) dest[idx]);
389  }
390  }
391 
392  return dest;
393 }
#define MIN(a, b)
Definition: memory.h:31
regex_t * regex
compiled expression
Definition: regex3.h:60
#define MAX(a, b)
Definition: memory.h:30
struct Regex * GecosMask
Config: Regex for parsing GECOS field of /etc/passwd.
Definition: muttlib.c:68
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:742

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

402 {
403  switch (m->type)
404  {
405  case TYPE_TEXT:
406  if (mutt_str_strcasecmp("plain", m->subtype) == 0)
407  return false;
408  break;
409  case TYPE_APPLICATION:
411  return false;
413  return false;
414  break;
415 
416  case TYPE_MULTIPART:
417  case TYPE_MESSAGE:
418  return false;
419  }
420 
421  return true;
422 }
char * subtype
content-type subtype
Definition: body.h:36
Type: &#39;text/*&#39;.
Definition: mime.h:38
int mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:510
unsigned int type
content-type primary type
Definition: body.h:67
#define APPLICATION_PGP
Definition: ncrypt.h:129
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:625
int mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:569
#define WithCrypto
Definition: ncrypt.h:154
Type: &#39;application/*&#39;.
Definition: mime.h:33
#define APPLICATION_SMIME
Definition: ncrypt.h:130

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

430 {
431  int t = b->type;
432  char *s = b->subtype;
433 
435  return false;
436 
437  if (t == TYPE_TEXT)
438  return true;
439 
440  if (t == TYPE_MESSAGE)
441  {
442  if (mutt_str_strcasecmp("delivery-status", s) == 0)
443  return true;
444  }
445 
446  if (((WithCrypto & APPLICATION_PGP) != 0) && t == TYPE_APPLICATION)
447  {
448  if (mutt_str_strcasecmp("pgp-keys", s) == 0)
449  return true;
450  }
451 
452  return false;
453 }
char * subtype
content-type subtype
Definition: body.h:36
Type: &#39;text/*&#39;.
Definition: mime.h:38
int mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:510
unsigned int type
content-type primary type
Definition: body.h:67
#define APPLICATION_PGP
Definition: ncrypt.h:129
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:625
#define WithCrypto
Definition: ncrypt.h:154
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 464 of file muttlib.c.

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

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

510 {
511  uint8_t *p = buf;
512 
513  if (mutt_randbuf(p, buflen) < 0)
514  mutt_exit(1);
515  for (size_t pos = 0; pos < buflen; pos++)
516  p[pos] = base32[p[pos] % 32];
517 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:464
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:197
static const unsigned char base32[]
Definition: muttlib.c:502

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

524 {
525  uint32_t ret = 0;
526 
527  if (mutt_randbuf(&ret, sizeof(ret)) < 0)
528  mutt_exit(1);
529  return ret;
530 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:464
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:197

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

537 {
538  uint64_t ret = 0;
539 
540  if (mutt_randbuf(&ret, sizeof(ret)) < 0)
541  mutt_exit(1);
542  return ret;
543 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:464
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:197

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

555 {
556  mutt_buffer_printf(buf, "%s/%s-%s-%d-%d-%ld%ld%s%s", NONULL(Tmpdir), NONULL(prefix),
557  NONULL(Hostname), (int) getuid(), (int) getpid(), random(),
558  random(), suffix ? "." : "", NONULL(suffix));
559  mutt_debug(3, "%s:%d: mutt_mktemp returns \"%s\".\n", src, line, mutt_b2s(buf));
560  if (unlink(mutt_b2s(buf)) && errno != ENOENT)
561  {
562  mutt_debug(1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src, line,
563  mutt_b2s(buf), strerror(errno), errno);
564  }
565 }
#define NONULL(x)
Definition: string2.h:39
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:200
const char * line
Definition: common.c:35
#define mutt_b2s(buf)
Definition: buffer.h:42
char * Tmpdir
Config: Directory for temporary files.
Definition: file.c:50
WHERE char * Hostname
Config: Fully-qualified domain name of this machine.
Definition: globals.h:111
#define mutt_debug(LEVEL,...)
Definition: logging.h:85

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

580 {
581  size_t n = snprintf(buf, buflen, "%s/%s-%s-%d-%d-%" PRIu64 "%s%s", NONULL(Tmpdir),
582  NONULL(prefix), NONULL(ShortHostname), (int) getuid(),
583  (int) getpid(), mutt_rand64(), suffix ? "." : "", NONULL(suffix));
584  if (n >= buflen)
585  {
586  mutt_debug(1,
587  "%s:%d: ERROR: insufficient buffer space to hold temporary "
588  "filename! buflen=%zu but need %zu\n",
589  src, line, buflen, n);
590  }
591  mutt_debug(3, "%s:%d: mutt_mktemp returns \"%s\".\n", src, line, buf);
592  if (unlink(buf) && errno != ENOENT)
593  {
594  mutt_debug(1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src, line,
595  buf, strerror(errno), errno);
596  }
597 }
#define NONULL(x)
Definition: string2.h:39
const char * line
Definition: common.c:35
char * Tmpdir
Config: Directory for temporary files.
Definition: file.c:50
uint64_t mutt_rand64(void)
Create a 64-bit random number.
Definition: muttlib.c:536
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:48
#define mutt_debug(LEVEL,...)
Definition: logging.h:85

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

607 {
608  char *p = buf, *q = buf;
609  size_t len;
610  enum UrlScheme scheme;
611  char tmp[PATH_MAX];
612 
613  scheme = url_check_scheme(buf);
614 
615  if (scheme == U_IMAP || scheme == U_IMAPS)
616  {
618  return;
619  }
620 
621  if (scheme == U_NOTMUCH)
622  return;
623 
624  /* if buf is an url, only collapse path component */
625  if (scheme != U_UNKNOWN)
626  {
627  p = strchr(buf, ':') + 1;
628  if (strncmp(p, "//", 2) == 0)
629  q = strchr(p + 2, '/');
630  if (!q)
631  q = strchr(p, '\0');
632  p = q;
633  }
634 
635  /* cleanup path */
636  if (strstr(p, "//") || strstr(p, "/./"))
637  {
638  /* first attempt to collapse the pathname, this is more
639  * lightweight than realpath() and doesn't resolve links
640  */
641  while (*p)
642  {
643  if (*p == '/' && p[1] == '/')
644  {
645  *q++ = '/';
646  p += 2;
647  }
648  else if (p[0] == '/' && p[1] == '.' && p[2] == '/')
649  {
650  *q++ = '/';
651  p += 3;
652  }
653  else
654  *q++ = *p++;
655  }
656  *q = 0;
657  }
658  else if (strstr(p, "..") && (scheme == U_UNKNOWN || scheme == U_FILE) && realpath(p, tmp))
659  mutt_str_strfcpy(p, tmp, buflen - (p - buf));
660 
661  if ((len = mutt_str_startswith(buf, Folder, CASE_MATCH)) && buf[len] == '/')
662  {
663  *buf++ = '=';
664  memmove(buf, buf + len, mutt_str_strlen(buf + len) + 1);
665  }
666  else if ((len = mutt_str_startswith(buf, HomeDir, CASE_MATCH)) && buf[len] == '/')
667  {
668  *buf++ = '~';
669  memmove(buf, buf + len - 1, mutt_str_strlen(buf + len - 1) + 1);
670  }
671 }
Url is notmuch://.
Definition: url.h:45
void imap_pretty_mailbox(char *path, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:693
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:69
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:663
UrlScheme
All recognised Url types.
Definition: url.h:32
WHERE char * HomeDir
User&#39;s home directory.
Definition: globals.h:47
enum UrlScheme url_check_scheme(const char *s)
Check the protocol of a URL.
Definition: url.c:133
A folder/dir in the browser.
Definition: browser.h:47
#define PATH_MAX
Definition: mutt.h:46
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:742
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:166
Url is file://.
Definition: url.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,
int *  append,
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]appendFlags set to MUTT_SAVE_APPEND or MUTT_SAVE_OVERWRITE
[out]directoryDirectory to save under (OPTIONAL)
Return values
0Success
-1Abort
1Error

Definition at line 685 of file muttlib.c.

687 {
688  struct stat st;
689 
690  mutt_str_strfcpy(fname, path, flen);
691  if (access(fname, F_OK) != 0)
692  return 0;
693  if (stat(fname, &st) != 0)
694  return -1;
695  if (S_ISDIR(st.st_mode))
696  {
697  int rc = 0;
698  if (directory)
699  {
700  switch (mutt_multi_choice
701  /* L10N:
702  Means "The path you specified as the destination file is a directory."
703  See the msgid "Save to file: " (alias.c, recvattach.c)
704 
705  These three letters correspond to the choices in the string.
706  */
707  (_("File is a directory, save under it? [(y)es, (n)o, (a)ll]"), _("yna")))
708  {
709  case 3: /* all */
710  mutt_str_replace(directory, fname);
711  break;
712  case 1: /* yes */
713  FREE(directory);
714  break;
715  case -1: /* abort */
716  FREE(directory);
717  return -1;
718  case 2: /* no */
719  FREE(directory);
720  return 1;
721  }
722  }
723  /* L10N:
724  Means "The path you specified as the destination file is a directory."
725  See the msgid "Save to file: " (alias.c, recvattach.c) */
726  else if ((rc = mutt_yesorno(_("File is a directory, save under it?"), MUTT_YES)) != MUTT_YES)
727  return (rc == MUTT_NO) ? 1 : -1;
728 
729  char tmp[PATH_MAX];
730  mutt_str_strfcpy(tmp, mutt_path_basename(NONULL(attname)), sizeof(tmp));
731  if (mutt_get_field(_("File under directory: "), tmp, sizeof(tmp),
732  MUTT_FILE | MUTT_CLEAR) != 0 ||
733  !tmp[0])
734  {
735  return -1;
736  }
737  mutt_path_concat(fname, path, tmp, flen);
738  }
739 
740  if (*append == 0 && access(fname, F_OK) == 0)
741  {
742  switch (
743  mutt_multi_choice(_("File exists, (o)verwrite, (a)ppend, or (c)ancel?"),
744  // L10N: Options for: File exists, (o)verwrite, (a)ppend, or (c)ancel?
745  _("oac")))
746  {
747  case -1: /* abort */
748  return -1;
749  case 3: /* cancel */
750  return 1;
751 
752  case 2: /* append */
753  *append = MUTT_SAVE_APPEND;
754  break;
755  case 1: /* overwrite */
756  *append = MUTT_SAVE_OVERWRITE;
757  break;
758  }
759  }
760  return 0;
761 }
#define NONULL(x)
Definition: string2.h:39
#define MUTT_CLEAR
clear input if printable character is pressed
Definition: mutt.h:63
const char * mutt_path_basename(const char *f)
Find the last component for a pathname.
Definition: path.c:303
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
int mutt_yesorno(const char *msg, int def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
Overwrite existing file - mutt_save_attachment()
Definition: mutt.h:182
#define _(a)
Definition: message.h:28
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:792
#define PATH_MAX
Definition: mutt.h:46
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:742
Append to existing file - mutt_save_attachment()
Definition: mutt.h:181
#define mutt_get_field(A, B, C, D)
Definition: curs_lib.h:78
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:460
#define MUTT_FILE
do file completion
Definition: mutt.h:59
#define FREE(x)
Definition: memory.h:46
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:323

+ 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,
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 trucated to the '@' character.

Definition at line 772 of file muttlib.c.

773 {
774  if (addr && addr->mailbox)
775  {
776  mutt_str_strfcpy(buf, addr->mailbox, buflen);
777  if (!SaveAddress)
778  {
779  char *p = strpbrk(buf, "%@");
780  if (p)
781  *p = 0;
782  }
783  mutt_str_strlower(buf);
784  }
785  else
786  *buf = 0;
787 }
WHERE bool SaveAddress
Config: Use sender&#39;s full address as a default save folder.
Definition: globals.h:250
char * mailbox
mailbox and host address
Definition: address.h:35
char * mutt_str_strlower(char *s)
convert all characters in the string to lowercase
Definition: string.c:513
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:742

+ 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,
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 797 of file muttlib.c.

798 {
799  mutt_save_path(buf, buflen, a);
800  for (char *p = buf; *p; p++)
801  if ((*p == '/') || ISSPACE(*p) || !IsPrint((unsigned char) *p))
802  *p = '_';
803 }
#define ISSPACE(c)
Definition: string2.h:40
#define IsPrint(c)
Definition: mbyte.h:38
void mutt_save_path(char *buf, size_t buflen, struct Address *addr)
Turn an email address into a filename (for saving)
Definition: muttlib.c:772

+ 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,
enum FormatFlag  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 816 of file muttlib.c.

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

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

1339 {
1340  FILE *f = NULL;
1341  struct stat s;
1342 
1343  size_t len = mutt_str_strlen(path);
1344  if (len == 0)
1345  {
1346  return NULL;
1347  }
1348 
1349  if (path[len - 1] == '|')
1350  {
1351  /* read from a pipe */
1352 
1353  char *p = mutt_str_strdup(path);
1354 
1355  p[len - 1] = 0;
1356  mutt_endwin();
1357  *thepid = mutt_create_filter(p, NULL, &f, NULL);
1358  FREE(&p);
1359  }
1360  else
1361  {
1362  if (stat(path, &s) < 0)
1363  return NULL;
1364  if (S_ISDIR(s.st_mode))
1365  {
1366  errno = EINVAL;
1367  return NULL;
1368  }
1369  f = fopen(path, "r");
1370  *thepid = -1;
1371  }
1372  return f;
1373 }
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:663
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:498
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
#define FREE(x)
Definition: memory.h:46
pid_t mutt_create_filter(const char *s, FILE **in, FILE **out, FILE **err)
Set up filter program.
Definition: filter.c:216

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

1384 {
1385  char tmp[PATH_MAX];
1386  int ret = 0;
1387  int rc;
1388 
1389  enum MailboxType magic = mx_path_probe(s, NULL);
1390 
1391 #ifdef USE_POP
1392  if (magic == MUTT_POP)
1393  {
1394  mutt_error(_("Can't save message to POP mailbox"));
1395  return 1;
1396  }
1397 #endif
1398 
1399  if ((magic != MUTT_MAILBOX_ERROR) && (magic != MUTT_UNKNOWN) && !mx_access(s, W_OK))
1400  {
1401  if (Confirmappend)
1402  {
1403  snprintf(tmp, sizeof(tmp), _("Append messages to %s?"), s);
1404  rc = mutt_yesorno(tmp, MUTT_YES);
1405  if (rc == MUTT_NO)
1406  ret = 1;
1407  else if (rc == MUTT_ABORT)
1408  ret = -1;
1409  }
1410  }
1411 
1412 #ifdef USE_NNTP
1413  if (magic == MUTT_NNTP)
1414  {
1415  mutt_error(_("Can't save message to news server"));
1416  return 0;
1417  }
1418 #endif
1419 
1420  if (stat(s, st) != -1)
1421  {
1422  if (magic == MUTT_MAILBOX_ERROR)
1423  {
1424  mutt_error(_("%s is not a mailbox"), s);
1425  return 1;
1426  }
1427  }
1428  else if (magic != MUTT_IMAP)
1429  {
1430  st->st_mtime = 0;
1431  st->st_atime = 0;
1432 
1433  /* pathname does not exist */
1434  if (errno == ENOENT)
1435  {
1436  if (Confirmcreate)
1437  {
1438  snprintf(tmp, sizeof(tmp), _("Create %s?"), s);
1439  rc = mutt_yesorno(tmp, MUTT_YES);
1440  if (rc == MUTT_NO)
1441  ret = 1;
1442  else if (rc == MUTT_ABORT)
1443  ret = -1;
1444  }
1445 
1446  /* user confirmed with MUTT_YES or set Confirmcreate */
1447  if (ret == 0)
1448  {
1449  /* create dir recursively */
1450  char *tmp_path = mutt_path_dirname(s);
1451  if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
1452  {
1453  /* report failure & abort */
1454  mutt_perror(s);
1455  FREE(&tmp_path);
1456  return 1;
1457  }
1458  FREE(&tmp_path);
1459  }
1460  }
1461  else
1462  {
1463  mutt_perror(s);
1464  return 1;
1465  }
1466  }
1467 
1469  return ret;
1470 }
#define mutt_perror(...)
Definition: logging.h:89
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: magic.h:41
User aborted the question (with Ctrl-G)
Definition: quad.h:37
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
int mutt_yesorno(const char *msg, int def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final &#39;/&#39;.
Definition: path.c:398
#define _(a)
Definition: message.h:28
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:69
#define PATH_MAX
Definition: mutt.h:46
MailboxType
Supported mailbox formats.
Definition: magic.h:33
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:38
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:796
Error occurred examining mailbox.
Definition: magic.h:35
WHERE bool Confirmappend
Config: Confirm before appending emails to a mailbox.
Definition: globals.h:209
Mailbox wasn&#39;t recognised.
Definition: magic.h:36
#define mutt_error(...)
Definition: logging.h:88
#define FREE(x)
Definition: memory.h:46
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
Definition: mx.c:162
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:41
WHERE bool Confirmcreate
Config: Confirm before creating a new mailbox.
Definition: globals.h:210
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1438
&#39;POP3&#39; Mailbox type
Definition: magic.h:44

+ 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 SleepTime is larger, sleep that long instead.

Definition at line 1478 of file muttlib.c.

1479 {
1480  if (SleepTime > s)
1481  sleep(SleepTime);
1482  else if (s)
1483  sleep(s);
1484 }
WHERE short SleepTime
Config: Time to pause after certain info messages.
Definition: globals.h:154

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

1493 {
1494  static char vstring[STRING];
1495  snprintf(vstring, sizeof(vstring), "NeoMutt %s%s", PACKAGE_VERSION, GitVer);
1496  return vstring;
1497 }
const char * GitVer
#define STRING
Definition: string2.h:35

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

1508 {
1509  char *p = mutt_str_strdup(src);
1510  int rc = mutt_ch_convert_string(&p, Charset, "us-ascii", 0);
1511  /* `src' may be NULL, such as when called from the pop3 driver. */
1512  size_t len = mutt_str_strfcpy(buf, (rc == 0) ? p : src, buflen);
1513 
1514  /* convert the path to POSIX "Portable Filename Character Set" */
1515  for (size_t i = 0; i < len; ++i)
1516  {
1517  if (!isalnum(buf[i]) && !strchr("/.-_", buf[i]))
1518  {
1519  buf[i] = '_';
1520  }
1521  }
1522  FREE(&p);
1523 }
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:715
char * Charset
Config: Default character set for displaying text on screen.
Definition: charset.c: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:742
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
#define FREE(x)
Definition: memory.h:46

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

1535 {
1536  const char *xdg_env = mutt_str_getenv(xdg_env_vars[type]);
1537  char *xdg = xdg_env ? mutt_str_strdup(xdg_env) : mutt_str_strdup(xdg_defaults[type]);
1538  char *x = xdg; /* strsep() changes xdg, so free x instead later */
1539  char *token = NULL;
1540  int rc = 0;
1541 
1542  while ((token = strsep(&xdg, ":")))
1543  {
1544  if (snprintf(buf, bufsize, "%s/%s/neomuttrc", token, PACKAGE) < 0)
1545  continue;
1546  mutt_expand_path(buf, bufsize);
1547  if (access(buf, F_OK) == 0)
1548  {
1549  rc = 1;
1550  break;
1551  }
1552 
1553  if (snprintf(buf, bufsize, "%s/%s/Muttrc", token, PACKAGE) < 0)
1554  continue;
1555  mutt_expand_path(buf, bufsize);
1556  if (access(buf, F_OK) == 0)
1557  {
1558  rc = 1;
1559  break;
1560  }
1561  }
1562 
1563  FREE(&x);
1564  return rc;
1565 }
static const char * xdg_env_vars[]
Definition: muttlib.c:70
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:157
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
#define FREE(x)
Definition: memory.h:46
static const char * xdg_defaults[]
Definition: muttlib.c:75

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_get_parent_path ( 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 1573 of file muttlib.c.

1574 {
1575  enum MailboxType mb_magic = mx_path_probe(path, NULL);
1576 
1577  if (mb_magic == MUTT_IMAP)
1578  imap_get_parent_path(path, buf, buflen);
1579  else if (mb_magic == MUTT_NOTMUCH)
1580  mutt_str_strfcpy(buf, Folder, buflen);
1581  else
1582  {
1583  mutt_str_strfcpy(buf, path, buflen);
1584  int n = mutt_str_strlen(buf);
1585  if (n == 0)
1586  return;
1587 
1588  /* remove any final trailing '/' */
1589  if (buf[n - 1] == '/')
1590  buf[n - 1] = '\0';
1591 
1592  /* Remove everything until the next slash */
1593  for (n--; ((n >= 0) && (buf[n] != '/')); n--)
1594  ;
1595 
1596  if (n > 0)
1597  buf[n] = '\0';
1598  else
1599  {
1600  buf[0] = '/';
1601  buf[1] = '\0';
1602  }
1603  }
1604 }
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: magic.h:43
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:663
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
Definition: util.c:304
A folder/dir in the browser.
Definition: browser.h:47
MailboxType
Supported mailbox formats.
Definition: magic.h:33
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:742
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1438

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

1629 {
1630  /* fast-track in case the paths have been mutt_pretty_mailbox'ified */
1631  if (a[0] == '+' && b[0] == '+')
1632  {
1633  return (mutt_str_strcasecmp(a + 1, "inbox") == 0) ?
1634  -1 :
1635  (mutt_str_strcasecmp(b + 1, "inbox") == 0) ? 1 : 0;
1636  }
1637 
1638  const char *a_end = strrchr(a, '/');
1639  const char *b_end = strrchr(b, '/');
1640 
1641  /* If one path contains a '/', but not the other */
1642  if (!a_end ^ !b_end)
1643  return 0;
1644 
1645  /* If neither path contains a '/' */
1646  if (!a_end)
1647  return 0;
1648 
1649  /* Compare the subpaths */
1650  size_t a_len = a_end - a;
1651  size_t b_len = b_end - b;
1652  size_t min = MIN(a_len, b_len);
1653  int same = (a[min] == '/') && (b[min] == '/') && (a[min + 1] != '\0') &&
1654  (b[min + 1] != '\0') && (mutt_str_strncasecmp(a, b, min) == 0);
1655 
1656  if (!same)
1657  return 0;
1658 
1659  if (mutt_str_strcasecmp(&a[min + 1], "inbox") == 0)
1660  return -1;
1661 
1662  if (mutt_str_strcasecmp(&b[min + 1], "inbox") == 0)
1663  return 1;
1664 
1665  return 0;
1666 }
#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:653
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:625

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation

struct Regex* GecosMask

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

Definition at line 68 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:44
XDG system dir: /etc/xdg.
Definition: protos.h:45

Definition at line 70 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:44
XDG system dir: /etc/xdg.
Definition: protos.h:45

Definition at line 75 of file muttlib.c.

FILE* frandom
static

Definition at line 455 of file muttlib.c.

const unsigned char base32[] = "abcdefghijklmnopqrstuvwxyz234567"
static

Definition at line 502 of file muttlib.c.