NeoMutt  2020-03-20-65-g141838
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/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "muttlib.h"
#include "alias.h"
#include "format_flags.h"
#include "globals.h"
#include "hook.h"
#include "init.h"
#include "mx.h"
#include "protos.h"
#include "ncrypt/lib.h"
#include "imap/lib.h"
+ Include dependency graph for muttlib.c:

Go to the source code of this file.

Functions

void mutt_adv_mktemp (struct Buffer *buf)
 Create a temporary file. More...
 
char * mutt_expand_path (char *buf, size_t buflen)
 Create the canonical path. More...
 
void mutt_buffer_expand_path_regex (struct Buffer *buf, bool regex)
 Create the canonical path (with regex char escaping) More...
 
void mutt_buffer_expand_path (struct Buffer *buf)
 Create the canonical path. More...
 
char * mutt_expand_path_regex (char *buf, size_t buflen, bool regex)
 Create the canonical path (with regex char escaping) More...
 
char * mutt_gecos_name (char *dest, size_t destlen, struct passwd *pw)
 Lookup a user's real name in /etc/passwd. More...
 
bool mutt_needs_mailcap (struct Body *m)
 Does this type need a mailcap entry do display. More...
 
bool mutt_is_text_part (struct Body *b)
 Is this part of an email in plain text? More...
 
int mutt_randbuf (void *buf, size_t buflen)
 Fill a buffer with randomness. More...
 
void mutt_rand_base32 (void *buf, size_t buflen)
 Fill a buffer with a base32-encoded random string. More...
 
uint32_t mutt_rand32 (void)
 Create a 32-bit random number. More...
 
uint64_t mutt_rand64 (void)
 Create a 64-bit random number. More...
 
void mutt_buffer_mktemp_full (struct Buffer *buf, const char *prefix, const char *suffix, const char *src, int line)
 Create a temporary file. More...
 
void mutt_mktemp_full (char *buf, size_t buflen, const char *prefix, const char *suffix, const char *src, int line)
 Create a temporary filename. More...
 
void mutt_pretty_mailbox (char *buf, size_t buflen)
 Shorten a mailbox path using '~' or '='. More...
 
void mutt_buffer_pretty_mailbox (struct Buffer *buf)
 Shorten a mailbox path using '~' or '='. More...
 
int mutt_check_overwrite (const char *attname, const char *path, struct Buffer *fname, enum SaveAttach *opt, char **directory)
 Ask the user if overwriting is necessary. More...
 
void mutt_save_path (char *buf, size_t buflen, const struct Address *addr)
 Turn an email address into a filename (for saving) More...
 
void mutt_buffer_save_path (struct Buffer *dest, const struct Address *a)
 Make a safe filename from an email address. More...
 
void mutt_safe_path (struct Buffer *dest, const struct Address *a)
 Make a safe filename from an email address. More...
 
void mutt_expando_format (char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long data, MuttFormatFlags flags)
 Expand expandos (x) in a string. More...
 
FILE * mutt_open_read (const char *path, pid_t *thepid)
 Run a command to read from. More...
 
int mutt_save_confirm (const char *s, struct stat *st)
 Ask the user to save. More...
 
void mutt_sleep (short s)
 Sleep for a while. More...
 
const char * mutt_make_version (void)
 Generate the NeoMutt version string. More...
 
void mutt_encode_path (struct Buffer *buf, const char *src)
 Convert a path to 'us-ascii'. More...
 
int mutt_set_xdg_path (enum XdgType type, char *buf, size_t bufsize)
 Find an XDG path or its fallback. More...
 
void mutt_get_parent_path (const char *path, char *buf, size_t buflen)
 Find the parent of a path (or mailbox) More...
 
int mutt_inbox_cmp (const char *a, const char *b)
 do two folders share the same path and one is an inbox More...
 
void mutt_buffer_sanitize_filename (struct Buffer *buf, const char *path, short slash)
 Replace unsafe characters in a filename. More...
 
void mutt_str_pretty_size (char *buf, size_t buflen, size_t num)
 Display an abbreviated size, like 3.4K. More...
 
void add_to_stailq (struct ListHead *head, const char *str)
 Add a string to a list. More...
 
void remove_from_stailq (struct ListHead *head, const char *str)
 Remove an item, matching a string, from a List. More...
 

Variables

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

Detailed Description

Some miscellaneous functions.

Authors
  • Michael R. Elkins
  • Thomas Roessler
  • Pietro Cerutti

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file muttlib.c.

Function Documentation

◆ mutt_adv_mktemp()

void mutt_adv_mktemp ( struct Buffer buf)

Create a temporary file.

Parameters
bufBuffer for the name

Accept a "suggestion" for file name. If that file exists, then construct one with unique name but keep any extension. This might fail, I guess.

Definition at line 95 of file muttlib.c.

96 {
97  if (!(buf->data && buf->data[0]))
98  {
99  mutt_buffer_mktemp(buf);
100  }
101  else
102  {
103  struct Buffer *prefix = mutt_buffer_pool_get();
104  mutt_buffer_strcpy(prefix, buf->data);
105  mutt_file_sanitize_filename(prefix->data, true);
106  mutt_buffer_printf(buf, "%s/%s", NONULL(C_Tmpdir), mutt_b2s(prefix));
107 
108  struct stat sb;
109  if ((lstat(mutt_b2s(buf), &sb) == -1) && (errno == ENOENT))
110  goto out;
111 
112  char *suffix = strchr(prefix->data, '.');
113  if (suffix)
114  {
115  *suffix = '\0';
116  suffix++;
117  }
118  mutt_buffer_mktemp_pfx_sfx(buf, prefix->data, suffix);
119 
120  out:
121  mutt_buffer_pool_release(&prefix);
122  }
123 }
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:81
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_buffer_mktemp_pfx_sfx(buf, prefix, suffix)
Definition: muttlib.h:82
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:618
#define mutt_b2s(buf)
Definition: buffer.h:41
char * data
Pointer to data.
Definition: buffer.h:35
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:56
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_expand_path()

char* mutt_expand_path ( char *  buf,
size_t  buflen 
)

Create the canonical path.

Parameters
bufBuffer with path
buflenLength of buffer
Return values
ptrThe expanded string
Note
The path is expanded in-place

Definition at line 133 of file muttlib.c.

134 {
135  return mutt_expand_path_regex(buf, buflen, false);
136 }
char * mutt_expand_path_regex(char *buf, size_t buflen, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:342
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_expand_path_regex()

void mutt_buffer_expand_path_regex ( struct Buffer buf,
bool  regex 
)

Create the canonical path (with regex char escaping)

Parameters
bufBuffer with path
regexIf true, escape any regex characters
Note
The path is expanded in-place

Definition at line 145 of file muttlib.c.

146 {
147  const char *s = NULL;
148  const char *tail = "";
149 
150  bool recurse = false;
151 
152  struct Buffer *p = mutt_buffer_pool_get();
153  struct Buffer *q = mutt_buffer_pool_get();
154  struct Buffer *tmp = mutt_buffer_pool_get();
155 
156  do
157  {
158  recurse = false;
159  s = mutt_b2s(buf);
160 
161  switch (*s)
162  {
163  case '~':
164  {
165  if ((s[1] == '/') || (s[1] == '\0'))
166  {
168  tail = s + 1;
169  }
170  else
171  {
172  char *t = strchr(s + 1, '/');
173  if (t)
174  *t = '\0';
175 
176  struct passwd *pw = getpwnam(s + 1);
177  if (pw)
178  {
179  mutt_buffer_strcpy(p, pw->pw_dir);
180  if (t)
181  {
182  *t = '/';
183  tail = t;
184  }
185  else
186  tail = "";
187  }
188  else
189  {
190  /* user not found! */
191  if (t)
192  *t = '/';
194  tail = s;
195  }
196  }
197  break;
198  }
199 
200  case '=':
201  case '+':
202  {
203  enum MailboxType mb_type = mx_path_probe(C_Folder);
204 
205  /* if folder = {host} or imap[s]://host/: don't append slash */
206  if ((mb_type == MUTT_IMAP) && ((C_Folder[strlen(C_Folder) - 1] == '}') ||
207  (C_Folder[strlen(C_Folder) - 1] == '/')))
208  {
210  }
211  else if (mb_type == MUTT_NOTMUCH)
213  else if (C_Folder && (C_Folder[strlen(C_Folder) - 1] == '/'))
215  else
216  mutt_buffer_printf(p, "%s/", NONULL(C_Folder));
217 
218  tail = s + 1;
219  break;
220  }
221 
222  /* elm compatibility, @ expands alias to user name */
223 
224  case '@':
225  {
226  struct AddressList *al = mutt_alias_lookup(s + 1);
227  if (al && !TAILQ_EMPTY(al))
228  {
229  struct Email *e = email_new();
230  e->env = mutt_env_new();
231  mutt_addrlist_copy(&e->env->from, al, false);
232  mutt_addrlist_copy(&e->env->to, al, false);
233 
234  /* TODO: fix mutt_default_save() to use Buffer */
236  mutt_default_save(p->data, p->dsize, e);
238 
239  email_free(&e);
240  /* Avoid infinite recursion if the resulting folder starts with '@' */
241  if (*p->data != '@')
242  recurse = true;
243 
244  tail = "";
245  }
246  break;
247  }
248 
249  case '>':
250  {
252  tail = s + 1;
253  break;
254  }
255 
256  case '<':
257  {
259  tail = s + 1;
260  break;
261  }
262 
263  case '!':
264  {
265  if (s[1] == '!')
266  {
268  tail = s + 2;
269  }
270  else
271  {
273  tail = s + 1;
274  }
275  break;
276  }
277 
278  case '-':
279  {
281  tail = s + 1;
282  break;
283  }
284 
285  case '^':
286  {
288  tail = s + 1;
289  break;
290  }
291 
292  default:
293  {
295  tail = s;
296  }
297  }
298 
299  if (regex && *(mutt_b2s(p)) && !recurse)
300  {
302  mutt_buffer_printf(tmp, "%s%s", mutt_b2s(q), tail);
303  }
304  else
305  mutt_buffer_printf(tmp, "%s%s", mutt_b2s(p), tail);
306 
307  mutt_buffer_copy(buf, tmp);
308  } while (recurse);
309 
313 
314 #ifdef USE_IMAP
315  /* Rewrite IMAP path in canonical form - aids in string comparisons of
316  * folders. May possibly fail, in which case buf should be the same. */
317  if (imap_path_probe(mutt_b2s(buf), NULL) == MUTT_IMAP)
318  imap_expand_path(buf);
319 #endif
320 }
#define NONULL(x)
Definition: string2.h:37
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct AddressList * mutt_alias_lookup(const char *s)
Find an Alias.
Definition: alias.c:285
The envelope/body of an email.
Definition: email.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2516
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer&#39;s contents to another Buffer.
Definition: buffer.c:445
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:728
String manipulation buffer.
Definition: buffer.h:33
WHERE char * LastFolder
Previously selected mailbox.
Definition: globals.h:55
WHERE char * C_Record
Config: Folder to save &#39;sent&#39; messages.
Definition: globals.h:132
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
void mutt_default_save(char *path, size_t pathlen, struct Email *e)
Find the default save path for an email.
Definition: hook.c:662
char * HomeDir
User&#39;s home directory.
Definition: globals.h:49
size_t dsize
Length of data.
Definition: buffer.h:37
int imap_expand_path(struct Buffer *buf)
Buffer wrapper around imap_path_canon()
Definition: imap.c:2562
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
WHERE char * C_Mbox
Config: Folder that receives read emails (see Move)
Definition: globals.h:119
struct Envelope * env
Envelope information.
Definition: email.h:89
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: globals.h:54
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
int mutt_file_sanitize_regex(struct Buffer *dest, const char *src)
Escape any regex-magic characters in a string.
Definition: file.c:637
#define mutt_b2s(buf)
Definition: buffer.h:41
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:121
#define PATH_MAX
Definition: mutt.h:44
char * data
Pointer to data.
Definition: buffer.h:35
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1318
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
WHERE char * C_Spoolfile
Config: Inbox.
Definition: globals.h:145
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
struct Email * email_new(void)
Create a new Email.
Definition: email.c:68
#define TAILQ_EMPTY(head)
Definition: queue.h:714
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:41
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_expand_path()

void mutt_buffer_expand_path ( struct Buffer buf)

Create the canonical path.

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

Definition at line 328 of file muttlib.c.

329 {
330  mutt_buffer_expand_path_regex(buf, false);
331 }
void mutt_buffer_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:145
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_expand_path_regex()

char* mutt_expand_path_regex ( char *  buf,
size_t  buflen,
bool  regex 
)

Create the canonical path (with regex char escaping)

Parameters
bufBuffer with path
buflenLength of buffer
regexIf true, escape any regex characters
Return values
ptrThe expanded string
Note
The path is expanded in-place

Definition at line 342 of file muttlib.c.

343 {
344  struct Buffer *tmp = mutt_buffer_pool_get();
345 
346  mutt_buffer_addstr(tmp, NONULL(buf));
347  mutt_buffer_expand_path_regex(tmp, regex);
348  mutt_str_strfcpy(buf, mutt_b2s(tmp), buflen);
349 
351 
352  return buf;
353 }
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
void mutt_buffer_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:145
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
#define mutt_b2s(buf)
Definition: buffer.h:41
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_gecos_name()

char* mutt_gecos_name ( char *  dest,
size_t  destlen,
struct passwd *  pw 
)

Lookup a user's real name in /etc/passwd.

Parameters
destBuffer for the result
destlenLength of buffer
pwPasswd entry
Return values
ptrResult buffer on success

Extract the real name from /etc/passwd's GECOS field. When set, honor the regular expression in C_GecosMask, otherwise assume that the GECOS field is a comma-separated list. Replace "&" by a capitalized version of the user's login name.

Definition at line 367 of file muttlib.c.

368 {
369  regmatch_t pat_match[1];
370  size_t pwnl;
371  char *p = NULL;
372 
373  if (!pw || !pw->pw_gecos)
374  return NULL;
375 
376  memset(dest, 0, destlen);
377 
378  if (mutt_regex_capture(C_GecosMask, pw->pw_gecos, 1, pat_match))
379  {
380  mutt_str_strfcpy(dest, pw->pw_gecos + pat_match[0].rm_so,
381  MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
382  }
383  else if ((p = strchr(pw->pw_gecos, ',')))
384  mutt_str_strfcpy(dest, pw->pw_gecos, MIN(destlen, p - pw->pw_gecos + 1));
385  else
386  mutt_str_strfcpy(dest, pw->pw_gecos, destlen);
387 
388  pwnl = strlen(pw->pw_name);
389 
390  for (int idx = 0; dest[idx]; idx++)
391  {
392  if (dest[idx] == '&')
393  {
394  memmove(&dest[idx + pwnl], &dest[idx + 1],
395  MAX((ssize_t)(destlen - idx - pwnl - 1), 0));
396  memcpy(&dest[idx], pw->pw_name, MIN(destlen - idx - 1, pwnl));
397  dest[idx] = toupper((unsigned char) dest[idx]);
398  }
399  }
400 
401  return dest;
402 }
#define MIN(a, b)
Definition: memory.h:31
#define MAX(a, b)
Definition: memory.h:30
struct Regex * C_GecosMask
Config: Regex for parsing GECOS field of /etc/passwd.
Definition: muttlib.c:71
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
bool mutt_regex_capture(const struct Regex *regex, const char *str, size_t nmatch, regmatch_t matches[])
match a regex against a string, with provided options
Definition: regex.c:594
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_needs_mailcap()

bool mutt_needs_mailcap ( struct Body m)

Does this type need a mailcap entry do display.

Parameters
mAttachment body to be displayed
Return values
trueNeoMutt requires a mailcap entry to display
falseotherwise

Definition at line 410 of file muttlib.c.

411 {
412  switch (m->type)
413  {
414  case TYPE_TEXT:
415  if (mutt_str_strcasecmp("plain", m->subtype) == 0)
416  return false;
417  break;
418  case TYPE_APPLICATION:
420  return false;
422  return false;
423  break;
424 
425  case TYPE_MULTIPART:
426  case TYPE_MESSAGE:
427  return false;
428  }
429 
430  return true;
431 }
#define WithCrypto
Definition: lib.h:163
char * subtype
content-type subtype
Definition: body.h:37
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:138
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:565
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:137
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:624
unsigned int type
content-type primary type
Definition: body.h:65
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:651
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_is_text_part()

bool mutt_is_text_part ( struct Body b)

Is this part of an email in plain text?

Parameters
bPart of an email
Return values
trueIf part is in plain text

Definition at line 438 of file muttlib.c.

439 {
440  int t = b->type;
441  char *s = b->subtype;
442 
444  return false;
445 
446  if (t == TYPE_TEXT)
447  return true;
448 
449  if (t == TYPE_MESSAGE)
450  {
451  if (mutt_str_strcasecmp("delivery-status", s) == 0)
452  return true;
453  }
454 
455  if (((WithCrypto & APPLICATION_PGP) != 0) && (t == TYPE_APPLICATION))
456  {
457  if (mutt_str_strcasecmp("pgp-keys", s) == 0)
458  return true;
459  }
460 
461  return false;
462 }
#define WithCrypto
Definition: lib.h:163
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:565
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:137
Type: &#39;text/*&#39;.
Definition: mime.h:38
unsigned int type
content-type primary type
Definition: body.h:65
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:651
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_randbuf()

int mutt_randbuf ( void *  buf,
size_t  buflen 
)

Fill a buffer with randomness.

Parameters
bufBuffer for result
buflenSize of buffer
Return values
0Success
-1Error

Definition at line 471 of file muttlib.c.

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

◆ mutt_rand_base32()

void mutt_rand_base32 ( void *  buf,
size_t  buflen 
)

Fill a buffer with a base32-encoded random string.

Parameters
bufBuffer for result
buflenLength of buffer

Definition at line 514 of file muttlib.c.

515 {
516  uint8_t *p = buf;
517 
518  if (mutt_randbuf(p, buflen) < 0)
519  mutt_exit(1);
520  for (size_t pos = 0; pos < buflen; pos++)
521  p[pos] = base32[p[pos] % 32];
522 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:471
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:137
static const unsigned char base32[]
Definition: muttlib.c:75
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_rand32()

uint32_t mutt_rand32 ( void  )

Create a 32-bit random number.

Return values
numRandom number

Definition at line 528 of file muttlib.c.

529 {
530  uint32_t num = 0;
531 
532  if (mutt_randbuf(&num, sizeof(num)) < 0)
533  mutt_exit(1);
534  return num;
535 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:471
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:137
+ Here is the call graph for this function:

◆ mutt_rand64()

uint64_t mutt_rand64 ( void  )

Create a 64-bit random number.

Return values
numRandom number

Definition at line 541 of file muttlib.c.

542 {
543  uint64_t num = 0;
544 
545  if (mutt_randbuf(&num, sizeof(num)) < 0)
546  mutt_exit(1);
547  return num;
548 }
int mutt_randbuf(void *buf, size_t buflen)
Fill a buffer with randomness.
Definition: muttlib.c:471
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:137
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_mktemp_full()

void mutt_buffer_mktemp_full ( struct Buffer buf,
const char *  prefix,
const char *  suffix,
const char *  src,
int  line 
)

Create a temporary file.

Parameters
bufBuffer for result
prefixPrefix for filename
suffixSuffix for filename
srcSource file of caller
lineSource line number of caller

Definition at line 558 of file muttlib.c.

560 {
561  mutt_buffer_printf(buf, "%s/%s-%s-%d-%d-%" PRIu64 "%s%s", NONULL(C_Tmpdir),
562  NONULL(prefix), NONULL(ShortHostname), (int) getuid(),
563  (int) getpid(), mutt_rand64(), suffix ? "." : "", NONULL(suffix));
564 
565  mutt_debug(LL_DEBUG3, "%s:%d: mutt_mktemp returns \"%s\"\n", src, line, mutt_b2s(buf));
566  if (unlink(mutt_b2s(buf)) && (errno != ENOENT))
567  {
568  mutt_debug(LL_DEBUG1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src,
569  line, mutt_b2s(buf), strerror(errno), errno);
570  }
571 }
#define NONULL(x)
Definition: string2.h:37
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
#define mutt_b2s(buf)
Definition: buffer.h:41
uint64_t mutt_rand64(void)
Create a 64-bit random number.
Definition: muttlib.c:541
Log at debug level 1.
Definition: logging.h:40
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:56
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:50
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int const char int line
Definition: acutest.h:602
Log at debug level 3.
Definition: logging.h:42

◆ mutt_mktemp_full()

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

Create a temporary filename.

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

Definition at line 584 of file muttlib.c.

586 {
587  size_t n =
588  snprintf(buf, buflen, "%s/%s-%s-%d-%d-%" PRIu64 "%s%s", NONULL(C_Tmpdir),
589  NONULL(prefix), NONULL(ShortHostname), (int) getuid(),
590  (int) getpid(), mutt_rand64(), suffix ? "." : "", NONULL(suffix));
591  if (n >= buflen)
592  {
594  "%s:%d: ERROR: insufficient buffer space to hold temporary "
595  "filename! buflen=%zu but need %zu\n",
596  src, line, buflen, n);
597  }
598  mutt_debug(LL_DEBUG3, "%s:%d: mutt_mktemp returns \"%s\"\n", src, line, buf);
599  if (unlink(buf) && (errno != ENOENT))
600  {
601  mutt_debug(LL_DEBUG1, "%s:%d: ERROR: unlink(\"%s\"): %s (errno %d)\n", src,
602  line, buf, strerror(errno), errno);
603  }
604 }
#define NONULL(x)
Definition: string2.h:37
uint64_t mutt_rand64(void)
Create a 64-bit random number.
Definition: muttlib.c:541
Log at debug level 1.
Definition: logging.h:40
int n
Definition: acutest.h:477
char * C_Tmpdir
Config: Directory for temporary files.
Definition: file.c:56
WHERE char * ShortHostname
Short version of the hostname.
Definition: globals.h:50
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int const char int line
Definition: acutest.h:602
Log at debug level 3.
Definition: logging.h:42
+ Here is the call graph for this function:

◆ mutt_pretty_mailbox()

void mutt_pretty_mailbox ( char *  buf,
size_t  buflen 
)

Shorten a mailbox path using '~' or '='.

Parameters
bufBuffer containing string to shorten
buflenLength of buffer

Collapse the pathname using ~ or = when possible

Definition at line 613 of file muttlib.c.

614 {
615  if (!buf)
616  return;
617 
618  char *p = buf, *q = buf;
619  size_t len;
620  enum UrlScheme scheme;
621  char tmp[PATH_MAX];
622 
623  scheme = url_check_scheme(buf);
624 
625  if ((scheme == U_IMAP) || (scheme == U_IMAPS))
626  {
627  imap_pretty_mailbox(buf, buflen, C_Folder);
628  return;
629  }
630 
631  if (scheme == U_NOTMUCH)
632  return;
633 
634  /* if buf is an url, only collapse path component */
635  if (scheme != U_UNKNOWN)
636  {
637  p = strchr(buf, ':') + 1;
638  if (strncmp(p, "//", 2) == 0)
639  q = strchr(p + 2, '/');
640  if (!q)
641  q = strchr(p, '\0');
642  p = q;
643  }
644 
645  /* cleanup path */
646  if (strstr(p, "//") || strstr(p, "/./"))
647  {
648  /* first attempt to collapse the pathname, this is more
649  * lightweight than realpath() and doesn't resolve links */
650  while (*p)
651  {
652  if ((p[0] == '/') && (p[1] == '/'))
653  {
654  *q++ = '/';
655  p += 2;
656  }
657  else if ((p[0] == '/') && (p[1] == '.') && (p[2] == '/'))
658  {
659  *q++ = '/';
660  p += 3;
661  }
662  else
663  *q++ = *p++;
664  }
665  *q = '\0';
666  }
667  else if (strstr(p, "..") && ((scheme == U_UNKNOWN) || (scheme == U_FILE)) &&
668  realpath(p, tmp))
669  {
670  mutt_str_strfcpy(p, tmp, buflen - (p - buf));
671  }
672 
673  if ((len = mutt_str_startswith(buf, C_Folder, CASE_MATCH)) && (buf[len] == '/'))
674  {
675  *buf++ = '=';
676  memmove(buf, buf + len, mutt_str_strlen(buf + len) + 1);
677  }
678  else if ((len = mutt_str_startswith(buf, HomeDir, CASE_MATCH)) && (buf[len] == '/'))
679  {
680  *buf++ = '~';
681  memmove(buf, buf + len - 1, mutt_str_strlen(buf + len - 1) + 1);
682  }
683 }
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition: url.c:219
Url is notmuch://.
Definition: url.h:45
Url is imaps://.
Definition: url.h:39
Url wasn&#39;t recognised.
Definition: url.h:34
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
Definition: util.c:732
Url is imap://.
Definition: url.h:38
Match case when comparing strings.
Definition: string2.h:67
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
char * HomeDir
User&#39;s home directory.
Definition: globals.h:49
UrlScheme
All recognised Url types.
Definition: url.h:32
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:121
#define PATH_MAX
Definition: mutt.h:44
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:773
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
Url is file://.
Definition: url.h:35
+ Here is the caller graph for this function:

◆ mutt_buffer_pretty_mailbox()

void mutt_buffer_pretty_mailbox ( struct Buffer buf)

Shorten a mailbox path using '~' or '='.

Parameters
bufBuffer containing Mailbox name

Definition at line 689 of file muttlib.c.

690 {
691  if (!buf || !buf->data)
692  return;
693  /* This reduces the size of the Buffer, so we can pass it through.
694  * We adjust the size just to make sure buf->data is not NULL though */
696  mutt_pretty_mailbox(buf->data, buf->dsize);
698 }
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:613
size_t dsize
Length of data.
Definition: buffer.h:37
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
#define PATH_MAX
Definition: mutt.h:44
char * data
Pointer to data.
Definition: buffer.h:35
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_check_overwrite()

int mutt_check_overwrite ( const char *  attname,
const char *  path,
struct Buffer fname,
enum SaveAttach opt,
char **  directory 
)

Ask the user if overwriting is necessary.

Parameters
[in]attnameAttachment name
[in]pathPath to save the file
[out]fnameBuffer for filename
[out]optSave option, see SaveAttach
[out]directoryDirectory to save under (OPTIONAL)
Return values
0Success
-1Abort
1Error

Definition at line 711 of file muttlib.c.

713 {
714  struct stat st;
715 
716  mutt_buffer_strcpy(fname, path);
717  if (access(mutt_b2s(fname), F_OK) != 0)
718  return 0;
719  if (stat(mutt_b2s(fname), &st) != 0)
720  return -1;
721  if (S_ISDIR(st.st_mode))
722  {
723  enum QuadOption ans = MUTT_NO;
724  if (directory)
725  {
726  switch (mutt_multi_choice
727  /* L10N: Means "The path you specified as the destination file is a directory."
728  See the msgid "Save to file: " (alias.c, recvattach.c)
729  These three letters correspond to the choices in the string. */
730  (_("File is a directory, save under it: (y)es, (n)o, (a)ll?"), _("yna")))
731  {
732  case 3: /* all */
733  mutt_str_replace(directory, mutt_b2s(fname));
734  break;
735  case 1: /* yes */
736  FREE(directory);
737  break;
738  case -1: /* abort */
739  FREE(directory);
740  return -1;
741  case 2: /* no */
742  FREE(directory);
743  return 1;
744  }
745  }
746  /* L10N: Means "The path you specified as the destination file is a directory."
747  See the msgid "Save to file: " (alias.c, recvattach.c) */
748  else if ((ans = mutt_yesorno(_("File is a directory, save under it?"), MUTT_YES)) != MUTT_YES)
749  return (ans == MUTT_NO) ? 1 : -1;
750 
751  struct Buffer *tmp = mutt_buffer_pool_get();
753  if ((mutt_buffer_get_field(_("File under directory: "), tmp, MUTT_FILE | MUTT_CLEAR) != 0) ||
755  {
757  return (-1);
758  }
759  mutt_buffer_concat_path(fname, path, mutt_b2s(tmp));
761  }
762 
763  if ((*opt == MUTT_SAVE_NO_FLAGS) && (access(mutt_b2s(fname), F_OK) == 0))
764  {
765  switch (
766  mutt_multi_choice(_("File exists, (o)verwrite, (a)ppend, or (c)ancel?"),
767  // L10N: Options for: File exists, (o)verwrite, (a)ppend, or (c)ancel?
768  _("oac")))
769  {
770  case -1: /* abort */
771  return -1;
772  case 3: /* cancel */
773  return 1;
774 
775  case 2: /* append */
776  *opt = MUTT_SAVE_APPEND;
777  break;
778  case 1: /* overwrite */
779  *opt = MUTT_SAVE_OVERWRITE;
780  break;
781  }
782  }
783  return 0;
784 }
#define NONULL(x)
Definition: string2.h:37
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:62
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
const char * mutt_path_basename(const char *f)
Find the last component for a pathname.
Definition: path.c:329
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
No flags set.
Definition: mutt_attach.h:55
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
Overwrite existing file.
Definition: mutt_attach.h:57
#define _(a)
Definition: message.h:28
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:378
#define mutt_b2s(buf)
Definition: buffer.h:41
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: curs_lib.c:911
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
#define MUTT_FILE
Do file completion.
Definition: mutt.h:58
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
#define mutt_buffer_get_field(field, buf, complete)
Definition: curs_lib.h:84
Append to existing file.
Definition: mutt_attach.h:56
#define FREE(x)
Definition: memory.h:40
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:374
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_save_path()

void mutt_save_path ( char *  buf,
size_t  buflen,
const struct Address addr 
)

Turn an email address into a filename (for saving)

Parameters
bufBuffer for the result
buflenLength of buffer
addrEmail address to use

If the user hasn't set $save_address the name will be truncated to the '@' character.

Definition at line 795 of file muttlib.c.

796 {
797  if (addr && addr->mailbox)
798  {
799  mutt_str_strfcpy(buf, addr->mailbox, buflen);
800  if (!C_SaveAddress)
801  {
802  char *p = strpbrk(buf, "%@");
803  if (p)
804  *p = '\0';
805  }
806  mutt_str_strlower(buf);
807  }
808  else
809  *buf = '\0';
810 }
char * mailbox
Mailbox and host address.
Definition: address.h:37
char * mutt_str_strlower(char *s)
Convert all characters in the string to lowercase.
Definition: string.c:509
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:773
WHERE bool C_SaveAddress
Config: Use sender&#39;s full address as a default save folder.
Definition: globals.h:245
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_save_path()

void mutt_buffer_save_path ( struct Buffer dest,
const struct Address a 
)

Make a safe filename from an email address.

Parameters
destBuffer for the result
aAddress to use

Definition at line 817 of file muttlib.c.

818 {
819  if (a && a->mailbox)
820  {
821  mutt_buffer_strcpy(dest, a->mailbox);
822  if (!C_SaveAddress)
823  {
824  char *p = strpbrk(dest->data, "%@");
825  if (p)
826  {
827  *p = '\0';
828  mutt_buffer_fix_dptr(dest);
829  }
830  }
831  mutt_str_strlower(dest->data);
832  }
833  else
834  mutt_buffer_reset(dest);
835 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
char * mailbox
Mailbox and host address.
Definition: address.h:37
char * mutt_str_strlower(char *s)
Convert all characters in the string to lowercase.
Definition: string.c:509
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
char * data
Pointer to data.
Definition: buffer.h:35
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
WHERE bool C_SaveAddress
Config: Use sender&#39;s full address as a default save folder.
Definition: globals.h:245
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_safe_path()

void mutt_safe_path ( struct Buffer dest,
const struct Address a 
)

Make a safe filename from an email address.

Parameters
destBuffer for the result
aAddress to use

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

Definition at line 844 of file muttlib.c.

845 {
846  mutt_buffer_save_path(dest, a);
847  for (char *p = dest->data; *p; p++)
848  if ((*p == '/') || IS_SPACE(*p) || !IsPrint((unsigned char) *p))
849  *p = '_';
850 }
void mutt_buffer_save_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
Definition: muttlib.c:817
#define IsPrint(ch)
Definition: mbyte.h:39
char * data
Pointer to data.
Definition: buffer.h:35
#define IS_SPACE(ch)
Definition: string2.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_expando_format()

void mutt_expando_format ( char *  buf,
size_t  buflen,
size_t  col,
int  cols,
const char *  src,
format_t callback,
unsigned long  data,
MuttFormatFlags  flags 
)

Expand expandos (x) in a string.

Parameters
[out]bufBuffer in which to save string
[in]buflenBuffer length
[in]colStarting column
[in]colsNumber of screen columns
[in]srcPrintf-like format string
[in]callbackCallback - Implements format_t
[in]dataCallback data
[in]flagsCallback flags

Definition at line 863 of file muttlib.c.

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

◆ mutt_open_read()

FILE* mutt_open_read ( const char *  path,
pid_t *  thepid 
)

Run a command to read from.

Parameters
[in]pathPath to command
[out]thepidPID of the command
Return values
ptrFile containing output of command

This function allows the user to specify a command to read stdout from in place of a normal file. If the last character in the string is a pipe (|), then we assume it is a command to run instead of a normal file.

Definition at line 1393 of file muttlib.c.

1394 {
1395  FILE *fp = NULL;
1396  struct stat s;
1397 
1398  size_t len = mutt_str_strlen(path);
1399  if (len == 0)
1400  {
1401  return NULL;
1402  }
1403 
1404  if (path[len - 1] == '|')
1405  {
1406  /* read from a pipe */
1407 
1408  char *p = mutt_str_strdup(path);
1409 
1410  p[len - 1] = 0;
1411  mutt_endwin();
1412  *thepid = filter_create(p, NULL, &fp, NULL);
1413  FREE(&p);
1414  }
1415  else
1416  {
1417  if (stat(path, &s) < 0)
1418  return NULL;
1419  if (S_ISDIR(s.st_mode))
1420  {
1421  errno = EINVAL;
1422  return NULL;
1423  }
1424  fp = fopen(path, "r");
1425  *thepid = -1;
1426  }
1427  return fp;
1428 }
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:547
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_save_confirm()

int mutt_save_confirm ( const char *  s,
struct stat *  st 
)

Ask the user to save.

Parameters
sSave location
stTimestamp
Return values
0if OK to proceed
-1to abort
1to retry

Definition at line 1438 of file muttlib.c.

1439 {
1440  int ret = 0;
1441 
1442  enum MailboxType type = mx_path_probe(s);
1443 
1444 #ifdef USE_POP
1445  if (type == MUTT_POP)
1446  {
1447  mutt_error(_("Can't save message to POP mailbox"));
1448  return 1;
1449  }
1450 #endif
1451 
1452  if ((type != MUTT_MAILBOX_ERROR) && (type != MUTT_UNKNOWN) && !mx_access(s, W_OK))
1453  {
1454  if (C_Confirmappend)
1455  {
1456  struct Buffer *tmp = mutt_buffer_pool_get();
1457  mutt_buffer_printf(tmp, _("Append messages to %s?"), s);
1458  enum QuadOption ans = mutt_yesorno(mutt_b2s(tmp), MUTT_YES);
1459  if (ans == MUTT_NO)
1460  ret = 1;
1461  else if (ans == MUTT_ABORT)
1462  ret = -1;
1464  }
1465  }
1466 
1467 #ifdef USE_NNTP
1468  if (type == MUTT_NNTP)
1469  {
1470  mutt_error(_("Can't save message to news server"));
1471  return 0;
1472  }
1473 #endif
1474 
1475  if (stat(s, st) != -1)
1476  {
1477  if (type == MUTT_MAILBOX_ERROR)
1478  {
1479  mutt_error(_("%s is not a mailbox"), s);
1480  return 1;
1481  }
1482  }
1483  else if (type != MUTT_IMAP)
1484  {
1485  st->st_mtime = 0;
1486  st->st_atime = 0;
1487 
1488  /* pathname does not exist */
1489  if (errno == ENOENT)
1490  {
1491  if (C_Confirmcreate)
1492  {
1493  struct Buffer *tmp = mutt_buffer_pool_get();
1494  mutt_buffer_printf(tmp, _("Create %s?"), s);
1495  enum QuadOption ans = mutt_yesorno(mutt_b2s(tmp), MUTT_YES);
1496  if (ans == MUTT_NO)
1497  ret = 1;
1498  else if (ans == MUTT_ABORT)
1499  ret = -1;
1501  }
1502 
1503  /* user confirmed with MUTT_YES or set C_Confirmcreate */
1504  if (ret == 0)
1505  {
1506  /* create dir recursively */
1507  char *tmp_path = mutt_path_dirname(s);
1508  if (mutt_file_mkdir(tmp_path, S_IRWXU) == -1)
1509  {
1510  /* report failure & abort */
1511  mutt_perror(s);
1512  FREE(&tmp_path);
1513  return 1;
1514  }
1515  FREE(&tmp_path);
1516  }
1517  }
1518  else
1519  {
1520  mutt_perror(s);
1521  return 1;
1522  }
1523  }
1524 
1526  return ret;
1527 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:52
User aborted the question (with Ctrl-G)
Definition: quad.h:38
WHERE bool C_Confirmappend
Config: Confirm before appending emails to a mailbox.
Definition: globals.h:209
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final &#39;/&#39;.
Definition: path.c:376
#define _(a)
Definition: message.h:28
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:47
Error occurred examining Mailbox.
Definition: mailbox.h:46
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
WHERE bool C_Confirmcreate
Config: Confirm before creating a new mailbox.
Definition: globals.h:210
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:378
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:876
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:112
#define mutt_b2s(buf)
Definition: buffer.h:41
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:55
User answered &#39;No&#39;, or assume &#39;No&#39;.
Definition: quad.h:39
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1318
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
Definition: mx.c:171
struct MuttWindow * MuttMessageWindow
Message Window.
Definition: mutt_window.c:46
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_sleep()

void mutt_sleep ( short  s)

Sleep for a while.

Parameters
sNumber of seconds to sleep

If the user config '$sleep_time' is larger, sleep that long instead.

Definition at line 1535 of file muttlib.c.

1536 {
1537  if (C_SleepTime > s)
1538  sleep(C_SleepTime);
1539  else if (s)
1540  sleep(s);
1541 }
WHERE short C_SleepTime
Config: Time to pause after certain info messages.
Definition: globals.h:151
+ Here is the caller graph for this function:

◆ mutt_make_version()

const char* mutt_make_version ( void  )

Generate the NeoMutt version string.

Return values
ptrVersion string
Note
This returns a pointer to a static buffer

Definition at line 1549 of file muttlib.c.

1550 {
1551  static char vstring[256];
1552  snprintf(vstring, sizeof(vstring), "NeoMutt %s%s", PACKAGE_VERSION, GitVer);
1553  return vstring;
1554 }
const char * GitVer
+ Here is the caller graph for this function:

◆ mutt_encode_path()

void mutt_encode_path ( struct Buffer buf,
const char *  src 
)

Convert a path to 'us-ascii'.

Parameters
bufBuffer for the result
srcPath to convert (OPTIONAL)

If src is NULL, the path in buf will be converted in-place.

Definition at line 1563 of file muttlib.c.

1564 {
1565  char *p = mutt_str_strdup(src);
1566  int rc = mutt_ch_convert_string(&p, C_Charset, "us-ascii", 0);
1567  size_t len = mutt_buffer_strcpy(buf, (rc == 0) ? NONULL(p) : NONULL(src));
1568 
1569  /* convert the path to POSIX "Portable Filename Character Set" */
1570  for (size_t i = 0; i < len; i++)
1571  {
1572  if (!isalnum(buf->data[i]) && !strchr("/.-_", buf->data[i]))
1573  {
1574  buf->data[i] = '_';
1575  }
1576  }
1577  FREE(&p);
1578 }
#define NONULL(x)
Definition: string2.h:37
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:748
char * data
Pointer to data.
Definition: buffer.h:35
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_set_xdg_path()

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

1590 {
1591  const char *xdg_env = mutt_str_getenv(xdg_env_vars[type]);
1592  char *xdg = xdg_env ? mutt_str_strdup(xdg_env) : mutt_str_strdup(xdg_defaults[type]);
1593  char *x = xdg; /* strsep() changes xdg, so free x instead later */
1594  char *token = NULL;
1595  int rc = 0;
1596 
1597  while ((token = strsep(&xdg, ":")))
1598  {
1599  if (snprintf(buf, bufsize, "%s/%s/neomuttrc", token, PACKAGE) < 0)
1600  continue;
1601  mutt_expand_path(buf, bufsize);
1602  if (access(buf, F_OK) == 0)
1603  {
1604  rc = 1;
1605  break;
1606  }
1607 
1608  if (snprintf(buf, bufsize, "%s/%s/Muttrc", token, PACKAGE) < 0)
1609  continue;
1610  mutt_expand_path(buf, bufsize);
1611  if (access(buf, F_OK) == 0)
1612  {
1613  rc = 1;
1614  break;
1615  }
1616  }
1617 
1618  FREE(&x);
1619  return rc;
1620 }
static const char * xdg_env_vars[]
Definition: muttlib.c:77
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1071
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:133
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define FREE(x)
Definition: memory.h:40
static const char * xdg_defaults[]
Definition: muttlib.c:82
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_parent_path()

void mutt_get_parent_path ( const char *  path,
char *  buf,
size_t  buflen 
)

Find the parent of a path (or mailbox)

Parameters
pathPath to use
bufBuffer for the result
buflenLength of buffer

Definition at line 1628 of file muttlib.c.

1629 {
1630  enum MailboxType mb_type = mx_path_probe(path);
1631 
1632  if (mb_type == MUTT_IMAP)
1633  imap_get_parent_path(path, buf, buflen);
1634  else if (mb_type == MUTT_NOTMUCH)
1635  mutt_str_strfcpy(buf, C_Folder, buflen);
1636  else
1637  {
1638  mutt_str_strfcpy(buf, path, buflen);
1639  int n = mutt_str_strlen(buf);
1640  if (n == 0)
1641  return;
1642 
1643  /* remove any final trailing '/' */
1644  if (buf[n - 1] == '/')
1645  buf[n - 1] = '\0';
1646 
1647  /* Remove everything until the next slash */
1648  for (n--; ((n >= 0) && (buf[n] != '/')); n--)
1649  ;
1650 
1651  if (n > 0)
1652  buf[n] = '\0';
1653  else
1654  {
1655  buf[0] = '/';
1656  buf[1] = '\0';
1657  }
1658  }
1659 }
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
Definition: util.c:307
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: globals.h:121
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:773
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1318
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
int n
Definition: acutest.h:477
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_inbox_cmp()

int mutt_inbox_cmp ( const char *  a,
const char *  b 
)

do two folders share the same path and one is an inbox

Parameters
aFirst path
bSecond path
Return values
-1if a is INBOX of b
0if none is INBOX
1if b is INBOX for a

This function compares two folder paths. It first looks for the position of the last common '/' character. If a valid position is found and it's not the last character in any of the two paths, the remaining parts of the paths are compared (case insensitively) with the string "INBOX". If one of the two paths matches, it's reported as being less than the other and the function returns -1 (a < b) or 1 (a > b). If no paths match the requirements, the two paths are considered equivalent and this function returns 0.

Examples:

  • mutt_inbox_cmp("/foo/bar", "/foo/baz") –> 0
  • mutt_inbox_cmp("/foo/bar/", "/foo/bar/inbox") –> 0
  • mutt_inbox_cmp("/foo/bar/sent", "/foo/bar/inbox") –> 1
  • mutt_inbox_cmp("=INBOX", "=Drafts") –> -1

Definition at line 1683 of file muttlib.c.

1684 {
1685  /* fast-track in case the paths have been mutt_pretty_mailbox'ified */
1686  if ((a[0] == '+') && (b[0] == '+'))
1687  {
1688  return (mutt_str_strcasecmp(a + 1, "inbox") == 0) ?
1689  -1 :
1690  (mutt_str_strcasecmp(b + 1, "inbox") == 0) ? 1 : 0;
1691  }
1692 
1693  const char *a_end = strrchr(a, '/');
1694  const char *b_end = strrchr(b, '/');
1695 
1696  /* If one path contains a '/', but not the other */
1697  if ((!a_end) ^ (!b_end))
1698  return 0;
1699 
1700  /* If neither path contains a '/' */
1701  if (!a_end)
1702  return 0;
1703 
1704  /* Compare the subpaths */
1705  size_t a_len = a_end - a;
1706  size_t b_len = b_end - b;
1707  size_t min = MIN(a_len, b_len);
1708  int same = (a[min] == '/') && (b[min] == '/') && (a[min + 1] != '\0') &&
1709  (b[min + 1] != '\0') && (mutt_str_strncasecmp(a, b, min) == 0);
1710 
1711  if (!same)
1712  return 0;
1713 
1714  if (mutt_str_strcasecmp(&a[min + 1], "inbox") == 0)
1715  return -1;
1716 
1717  if (mutt_str_strcasecmp(&b[min + 1], "inbox") == 0)
1718  return 1;
1719 
1720  return 0;
1721 }
#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:679
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_buffer_sanitize_filename()

void mutt_buffer_sanitize_filename ( struct Buffer buf,
const char *  path,
short  slash 
)

Replace unsafe characters in a filename.

Parameters
bufBuffer for the result
pathFilename to make safe
slashReplace '/' characters too

Definition at line 1729 of file muttlib.c.

1730 {
1731  if (!buf || !path)
1732  return;
1733 
1734  mutt_buffer_reset(buf);
1735 
1736  for (; *path; path++)
1737  {
1738  if ((slash && (*path == '/')) || !strchr(filename_safe_chars, *path))
1739  mutt_buffer_addch(buf, '_');
1740  else
1741  mutt_buffer_addch(buf, *path);
1742  }
1743 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
const char filename_safe_chars[]
Definition: file.c:61
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_str_pretty_size()

void mutt_str_pretty_size ( char *  buf,
size_t  buflen,
size_t  num 
)

Display an abbreviated size, like 3.4K.

Parameters
bufBuffer for the result
buflenLength of the buffer
numNumber to abbreviate

Definition at line 1751 of file muttlib.c.

1752 {
1753  if (!buf || (buflen == 0))
1754  return;
1755 
1756  if (C_SizeShowBytes && (num < 1024))
1757  {
1758  snprintf(buf, buflen, "%d", (int) num);
1759  }
1760  else if (num == 0)
1761  {
1762  mutt_str_strfcpy(buf, C_SizeUnitsOnLeft ? "K0" : "0K", buflen);
1763  }
1764  else if (C_SizeShowFractions && (num < 10189)) /* 0.1K - 9.9K */
1765  {
1766  snprintf(buf, buflen, C_SizeUnitsOnLeft ? "K%3.1f" : "%3.1fK",
1767  (num < 103) ? 0.1 : (num / 1024.0));
1768  }
1769  else if (!C_SizeShowMb || (num < 1023949)) /* 10K - 999K */
1770  {
1771  /* 51 is magic which causes 10189/10240 to be rounded up to 10 */
1772  snprintf(buf, buflen, C_SizeUnitsOnLeft ? ("K%zu") : ("%zuK"), (num + 51) / 1024);
1773  }
1774  else if (C_SizeShowFractions && (num < 10433332)) /* 1.0M - 9.9M */
1775  {
1776  snprintf(buf, buflen, C_SizeUnitsOnLeft ? "M%3.1f" : "%3.1fM", num / 1048576.0);
1777  }
1778  else /* 10M+ */
1779  {
1780  /* (10433332 + 52428) / 1048576 = 10 */
1781  snprintf(buf, buflen, C_SizeUnitsOnLeft ? ("M%zu") : ("%zuM"), (num + 52428) / 1048576);
1782  }
1783 }
WHERE bool C_SizeShowFractions
Config: Show size fractions with a single decimal place.
Definition: globals.h:249
WHERE bool C_SizeShowMb
Config: Show sizes in megabytes for sizes greater than 1 megabyte.
Definition: globals.h:250
WHERE bool C_SizeUnitsOnLeft
Config: Show the units as a prefix to the size.
Definition: globals.h:251
WHERE bool C_SizeShowBytes
Config: Show smaller sizes in bytes.
Definition: globals.h:248
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:773
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ add_to_stailq()

void add_to_stailq ( struct ListHead *  head,
const char *  str 
)

Add a string to a list.

Parameters
headString list
strString to add
Note
Duplicate or empty strings will not be added

Definition at line 1792 of file muttlib.c.

1793 {
1794  /* don't add a NULL or empty string to the list */
1795  if (!str || (*str == '\0'))
1796  return;
1797 
1798  /* check to make sure the item is not already on this list */
1799  struct ListNode *np = NULL;
1800  STAILQ_FOREACH(np, head, entries)
1801  {
1802  if (mutt_str_strcasecmp(str, np->data) == 0)
1803  {
1804  return;
1805  }
1806  }
1808 }
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:65
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
char * data
String.
Definition: list.h:35
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
A List node for strings.
Definition: list.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_from_stailq()

void remove_from_stailq ( struct ListHead *  head,
const char *  str 
)

Remove an item, matching a string, from a List.

Parameters
headHead of the List
strString to match
Note
The string comparison is case-insensitive

Definition at line 1817 of file muttlib.c.

1818 {
1819  if (mutt_str_strcmp("*", str) == 0)
1820  mutt_list_free(head); /* "unCMD *" means delete all current entries */
1821  else
1822  {
1823  struct ListNode *np = NULL, *tmp = NULL;
1824  STAILQ_FOREACH_SAFE(np, head, entries, tmp)
1825  {
1826  if (mutt_str_strcasecmp(str, np->data) == 0)
1827  {
1828  STAILQ_REMOVE(head, np, ListNode, entries);
1829  FREE(&np->data);
1830  FREE(&np);
1831  break;
1832  }
1833  }
1834  }
1835 }
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:399
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:359
char * data
String.
Definition: list.h:35
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:651
#define FREE(x)
Definition: memory.h:40
A List node for strings.
Definition: list.h:33
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:638
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ C_GecosMask

struct Regex* C_GecosMask

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

Definition at line 71 of file muttlib.c.

◆ fp_random

FILE* fp_random
static

Definition at line 73 of file muttlib.c.

◆ base32

const unsigned char base32[] = "abcdefghijklmnopqrstuvwxyz234567"
static

Definition at line 75 of file muttlib.c.

◆ xdg_env_vars

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

Definition at line 77 of file muttlib.c.

◆ xdg_defaults

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

Definition at line 82 of file muttlib.c.