NeoMutt  2018-07-16 +1360-3df4a2
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, enum SaveAttach *opt, 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, 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 (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 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

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(C_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 mutt_buffer_mktemp(buf)
Definition: muttlib.h:75
#define NONULL(x)
Definition: string2.h:36
#define mutt_buffer_mktemp_pfx_sfx(buf, prefix, suffix)
Definition: muttlib.h:76
void mutt_file_sanitize_filename(char *fp, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:576
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:200
#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
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
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:50

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

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

354 {
355  regmatch_t pat_match[1];
356  size_t pwnl;
357  char *p = NULL;
358 
359  if (!pw || !pw->pw_gecos)
360  return NULL;
361 
362  memset(dest, 0, destlen);
363 
364  if (C_GecosMask && C_GecosMask->regex)
365  {
366  if (regexec(C_GecosMask->regex, pw->pw_gecos, 1, pat_match, 0) == 0)
367  {
368  mutt_str_strfcpy(dest, pw->pw_gecos + pat_match[0].rm_so,
369  MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
370  }
371  }
372  else if ((p = strchr(pw->pw_gecos, ',')))
373  mutt_str_strfcpy(dest, pw->pw_gecos, MIN(destlen, p - pw->pw_gecos + 1));
374  else
375  mutt_str_strfcpy(dest, pw->pw_gecos, destlen);
376 
377  pwnl = strlen(pw->pw_name);
378 
379  for (int idx = 0; dest[idx]; idx++)
380  {
381  if (dest[idx] == '&')
382  {
383  memmove(&dest[idx + pwnl], &dest[idx + 1],
384  MAX((ssize_t)(destlen - idx - pwnl - 1), 0));
385  memcpy(&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl));
386  dest[idx] = toupper((unsigned char) dest[idx]);
387  }
388  }
389 
390  return dest;
391 }
#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 * C_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:741

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

400 {
401  switch (m->type)
402  {
403  case TYPE_TEXT:
404  if (mutt_str_strcasecmp("plain", m->subtype) == 0)
405  return false;
406  break;
407  case TYPE_APPLICATION:
409  return false;
411  return false;
412  break;
413 
414  case TYPE_MULTIPART:
415  case TYPE_MESSAGE:
416  return false;
417  }
418 
419  return true;
420 }
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:525
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:584
unsigned int type
content-type primary type
Definition: body.h:70
#define APPLICATION_PGP
Use PGP to encrypt/sign.
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:624
#define WithCrypto
Definition: ncrypt.h:155
Type: &#39;application/*&#39;.
Definition: mime.h:33
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
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 427 of file muttlib.c.

428 {
429  int t = b->type;
430  char *s = b->subtype;
431 
433  return false;
434 
435  if (t == TYPE_TEXT)
436  return true;
437 
438  if (t == TYPE_MESSAGE)
439  {
440  if (mutt_str_strcasecmp("delivery-status", s) == 0)
441  return true;
442  }
443 
444  if (((WithCrypto & APPLICATION_PGP) != 0) && (t == TYPE_APPLICATION))
445  {
446  if (mutt_str_strcasecmp("pgp-keys", s) == 0)
447  return true;
448  }
449 
450  return false;
451 }
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:525
Type: &#39;text/*&#39;.
Definition: mime.h:38
unsigned int type
content-type primary type
Definition: body.h:70
#define APPLICATION_PGP
Use PGP to encrypt/sign.
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:624
#define WithCrypto
Definition: ncrypt.h:155
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 462 of file muttlib.c.

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

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

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

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

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

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

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

553 {
554  mutt_buffer_printf(buf, "%s/%s-%s-%d-%d-%ld%ld%s%s", NONULL(C_Tmpdir), NONULL(prefix),
555  NONULL(C_Hostname), (int) getuid(), (int) getpid(),
556  random(), random(), suffix ? "." : "", NONULL(suffix));
557  mutt_debug(LL_DEBUG3, "%s:%d: mutt_mktemp returns \"%s\".\n", src, line, mutt_b2s(buf));
558  if (unlink(mutt_b2s(buf)) && (errno != ENOENT))
559  {
560  mutt_debug(LL_DEBUG1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src,
561  line, mutt_b2s(buf), strerror(errno), errno);
562  }
563 }
#define NONULL(x)
Definition: string2.h:36
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
Log at debug level 1.
Definition: logging.h:56
WHERE char * C_Hostname
Config: Fully-qualified domain name of this machine.
Definition: globals.h:114
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 3.
Definition: logging.h:58
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:50

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

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

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

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

686 {
687  struct stat st;
688 
689  mutt_str_strfcpy(fname, path, flen);
690  if (access(fname, F_OK) != 0)
691  return 0;
692  if (stat(fname, &st) != 0)
693  return -1;
694  if (S_ISDIR(st.st_mode))
695  {
696  enum QuadOption ans = MUTT_NO;
697  if (directory)
698  {
699  switch (mutt_multi_choice
700  /* L10N: Means "The path you specified as the destination file is a directory."
701  See the msgid "Save to file: " (alias.c, recvattach.c)
702  These three letters correspond to the choices in the string. */
703  (_("File is a directory, save under it? [(y)es, (n)o, (a)ll]"), _("yna")))
704  {
705  case 3: /* all */
706  mutt_str_replace(directory, fname);
707  break;
708  case 1: /* yes */
709  FREE(directory);
710  break;
711  case -1: /* abort */
712  FREE(directory);
713  return -1;
714  case 2: /* no */
715  FREE(directory);
716  return 1;
717  }
718  }
719  /* L10N: Means "The path you specified as the destination file is a directory."
720  See the msgid "Save to file: " (alias.c, recvattach.c) */
721  else if ((ans = mutt_yesorno(_("File is a directory, save under it?"), MUTT_YES)) != MUTT_YES)
722  return (ans == MUTT_NO) ? 1 : -1;
723 
724  char tmp[PATH_MAX];
725  mutt_str_strfcpy(tmp, mutt_path_basename(NONULL(attname)), sizeof(tmp));
726  if ((mutt_get_field(_("File under directory: "), tmp, sizeof(tmp),
727  MUTT_FILE | MUTT_CLEAR) != 0) ||
728  !tmp[0])
729  {
730  return -1;
731  }
732  mutt_path_concat(fname, path, tmp, flen);
733  }
734 
735  if ((*opt == MUTT_SAVE_NO_FLAGS) && (access(fname, F_OK) == 0))
736  {
737  switch (
738  mutt_multi_choice(_("File exists, (o)verwrite, (a)ppend, or (c)ancel?"),
739  // L10N: Options for: File exists, (o)verwrite, (a)ppend, or (c)ancel?
740  _("oac")))
741  {
742  case -1: /* abort */
743  return -1;
744  case 3: /* cancel */
745  return 1;
746 
747  case 2: /* append */
748  *opt = MUTT_SAVE_APPEND;
749  break;
750  case 1: /* overwrite */
751  *opt = MUTT_SAVE_OVERWRITE;
752  break;
753  }
754  }
755  return 0;
756 }
#define NONULL(x)
Definition: string2.h:36
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:66
const char * mutt_path_basename(const char *f)
Find the last component for a pathname.
Definition: path.c:304
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:77
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
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:48
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:741
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:459
#define MUTT_FILE
Do file completion.
Definition: mutt.h:62
Append to existing file.
Definition: mutt_attach.h:55
#define FREE(x)
Definition: memory.h:40
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:324
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,
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 767 of file muttlib.c.

768 {
769  if (addr && addr->mailbox)
770  {
771  mutt_str_strfcpy(buf, addr->mailbox, buflen);
772  if (!C_SaveAddress)
773  {
774  char *p = strpbrk(buf, "%@");
775  if (p)
776  *p = '\0';
777  }
778  mutt_str_strlower(buf);
779  }
780  else
781  *buf = '\0';
782 }
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:512
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:741
WHERE bool C_SaveAddress
Config: Use sender&#39;s full address as a default save folder.
Definition: globals.h:254

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

793 {
794  mutt_save_path(buf, buflen, a);
795  for (char *p = buf; *p; p++)
796  if ((*p == '/') || ISSPACE(*p) || !IsPrint((unsigned char) *p))
797  *p = '_';
798 }
#define IsPrint(ch)
Definition: mbyte.h:38
#define ISSPACE(ch)
Definition: string2.h:37
void mutt_save_path(char *buf, size_t buflen, struct Address *addr)
Turn an email address into a filename (for saving)
Definition: muttlib.c:767

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

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

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

1333 {
1334  FILE *fp = NULL;
1335  struct stat s;
1336 
1337  size_t len = mutt_str_strlen(path);
1338  if (len == 0)
1339  {
1340  return NULL;
1341  }
1342 
1343  if (path[len - 1] == '|')
1344  {
1345  /* read from a pipe */
1346 
1347  char *p = mutt_str_strdup(path);
1348 
1349  p[len - 1] = 0;
1350  mutt_endwin();
1351  *thepid = mutt_create_filter(p, NULL, &fp, NULL);
1352  FREE(&p);
1353  }
1354  else
1355  {
1356  if (stat(path, &s) < 0)
1357  return NULL;
1358  if (S_ISDIR(s.st_mode))
1359  {
1360  errno = EINVAL;
1361  return NULL;
1362  }
1363  fp = fopen(path, "r");
1364  *thepid = -1;
1365  }
1366  return fp;
1367 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:216
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:662
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:497
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
#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 1377 of file muttlib.c.

1378 {
1379  char tmp[PATH_MAX];
1380  int ret = 0;
1381 
1382  enum MailboxType magic = mx_path_probe(s, NULL);
1383 
1384 #ifdef USE_POP
1385  if (magic == MUTT_POP)
1386  {
1387  mutt_error(_("Can't save message to POP mailbox"));
1388  return 1;
1389  }
1390 #endif
1391 
1392  if ((magic != MUTT_MAILBOX_ERROR) && (magic != MUTT_UNKNOWN) && !mx_access(s, W_OK))
1393  {
1394  if (C_Confirmappend)
1395  {
1396  snprintf(tmp, sizeof(tmp), _("Append messages to %s?"), s);
1397  enum QuadOption ans = mutt_yesorno(tmp, MUTT_YES);
1398  if (ans == MUTT_NO)
1399  ret = 1;
1400  else if (ans == MUTT_ABORT)
1401  ret = -1;
1402  }
1403  }
1404 
1405 #ifdef USE_NNTP
1406  if (magic == MUTT_NNTP)
1407  {
1408  mutt_error(_("Can't save message to news server"));
1409  return 0;
1410  }
1411 #endif
1412 
1413  if (stat(s, st) != -1)
1414  {
1415  if (magic == MUTT_MAILBOX_ERROR)
1416  {
1417  mutt_error(_("%s is not a mailbox"), s);
1418  return 1;
1419  }
1420  }
1421  else if (magic != MUTT_IMAP)
1422  {
1423  st->st_mtime = 0;
1424  st->st_atime = 0;
1425 
1426  /* pathname does not exist */
1427  if (errno == ENOENT)
1428  {
1429  if (C_Confirmcreate)
1430  {
1431  snprintf(tmp, sizeof(tmp), _("Create %s?"), s);
1432  enum QuadOption ans = mutt_yesorno(tmp, MUTT_YES);
1433  if (ans == MUTT_NO)
1434  ret = 1;
1435  else if (ans == MUTT_ABORT)
1436  ret = -1;
1437  }
1438 
1439  /* user confirmed with MUTT_YES or set C_Confirmcreate */
1440  if (ret == 0)
1441  {
1442  /* create dir recursively */
1443  char *tmp_path = mutt_path_dirname(s);
1444  if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
1445  {
1446  /* report failure & abort */
1447  mutt_perror(s);
1448  FREE(&tmp_path);
1449  return 1;
1450  }
1451  FREE(&tmp_path);
1452  }
1453  }
1454  else
1455  {
1456  mutt_perror(s);
1457  return 1;
1458  }
1459  }
1460 
1462  return ret;
1463 }
#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
WHERE bool C_Confirmappend
Config: Confirm before appending emails to a mailbox.
Definition: globals.h:213
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:398
#define _(a)
Definition: message.h:28
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
WHERE bool C_Confirmcreate
Config: Confirm before creating a new mailbox.
Definition: globals.h:214
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:330
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:48
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:794
Error occurred examining mailbox.
Definition: magic.h:35
Mailbox wasn&#39;t recognised.
Definition: magic.h:36
#define mutt_error(...)
Definition: logging.h:88
#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:162
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:41
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1207
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
&#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 '$sleep_time' is larger, sleep that long instead.

Definition at line 1471 of file muttlib.c.

1472 {
1473  if (C_SleepTime > s)
1474  sleep(C_SleepTime);
1475  else if (s)
1476  sleep(s);
1477 }
WHERE short C_SleepTime
Config: Time to pause after certain info messages.
Definition: globals.h:157

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

1486 {
1487  static char vstring[256];
1488  snprintf(vstring, sizeof(vstring), "NeoMutt %s%s", PACKAGE_VERSION, GitVer);
1489  return vstring;
1490 }
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 1500 of file muttlib.c.

1501 {
1502  char *p = mutt_str_strdup(src);
1503  int rc = mutt_ch_convert_string(&p, C_Charset, "us-ascii", 0);
1504  /* 'src' may be NULL, such as when called from the pop3 driver. */
1505  size_t len = mutt_str_strfcpy(buf, (rc == 0) ? p : src, buflen);
1506 
1507  /* convert the path to POSIX "Portable Filename Character Set" */
1508  for (size_t i = 0; i < len; i++)
1509  {
1510  if (!isalnum(buf[i]) && !strchr("/.-_", buf[i]))
1511  {
1512  buf[i] = '_';
1513  }
1514  }
1515  FREE(&p);
1516 }
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:717
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:741
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:383
#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 1527 of file muttlib.c.

1528 {
1529  const char *xdg_env = mutt_str_getenv(xdg_env_vars[type]);
1530  char *xdg = xdg_env ? mutt_str_strdup(xdg_env) : mutt_str_strdup(xdg_defaults[type]);
1531  char *x = xdg; /* strsep() changes xdg, so free x instead later */
1532  char *token = NULL;
1533  int rc = 0;
1534 
1535  while ((token = strsep(&xdg, ":")))
1536  {
1537  if (snprintf(buf, bufsize, "%s/%s/neomuttrc", token, PACKAGE) < 0)
1538  continue;
1539  mutt_expand_path(buf, bufsize);
1540  if (access(buf, F_OK) == 0)
1541  {
1542  rc = 1;
1543  break;
1544  }
1545 
1546  if (snprintf(buf, bufsize, "%s/%s/Muttrc", token, PACKAGE) < 0)
1547  continue;
1548  mutt_expand_path(buf, bufsize);
1549  if (access(buf, F_OK) == 0)
1550  {
1551  rc = 1;
1552  break;
1553  }
1554  }
1555 
1556  FREE(&x);
1557  return rc;
1558 }
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:1048
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:383
#define FREE(x)
Definition: memory.h:40
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 1566 of file muttlib.c.

1567 {
1568  enum MailboxType mb_magic = mx_path_probe(path, NULL);
1569 
1570  if (mb_magic == MUTT_IMAP)
1571  imap_get_parent_path(path, buf, buflen);
1572  else if (mb_magic == MUTT_NOTMUCH)
1573  mutt_str_strfcpy(buf, C_Folder, buflen);
1574  else
1575  {
1576  mutt_str_strfcpy(buf, path, buflen);
1577  int n = mutt_str_strlen(buf);
1578  if (n == 0)
1579  return;
1580 
1581  /* remove any final trailing '/' */
1582  if (buf[n - 1] == '/')
1583  buf[n - 1] = '\0';
1584 
1585  /* Remove everything until the next slash */
1586  for (n--; ((n >= 0) && (buf[n] != '/')); n--)
1587  ;
1588 
1589  if (n > 0)
1590  buf[n] = '\0';
1591  else
1592  {
1593  buf[0] = '/';
1594  buf[1] = '\0';
1595  }
1596  }
1597 }
&#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:662
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
Definition: util.c:301
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:122
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:741
enum MailboxType mx_path_probe(const char *path, struct stat *st)
Find a mailbox that understands a path.
Definition: mx.c:1207

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

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

+ 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 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:47
XDG system dir: /etc/xdg.
Definition: protos.h:48

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:47
XDG system dir: /etc/xdg.
Definition: protos.h:48

Definition at line 75 of file muttlib.c.

FILE* fp_random
static

Definition at line 453 of file muttlib.c.

const unsigned char base32[] = "abcdefghijklmnopqrstuvwxyz234567"
static

Definition at line 500 of file muttlib.c.