Go to the documentation of this file.
60 #if defined(HAVE_SYSCALL_H)
62 #elif defined(HAVE_SYS_SYSCALL_H)
63 #include <sys/syscall.h>
92 if (!(buf->
data && (buf->
data[0] !=
'\0')))
107 char *suffix = strchr(prefix->
data,
'.');
142 const char *s = NULL;
143 const char *tail =
"";
145 bool recurse =
false;
160 if ((s[1] ==
'/') || (s[1] ==
'\0'))
167 char *t = strchr(s + 1,
'/');
171 struct passwd *pw = getpwnam(s + 1);
364 regmatch_t pat_match[1];
368 if (!pw || !pw->pw_gecos)
371 memset(dest, 0, destlen);
376 MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
378 else if ((p = strchr(pw->pw_gecos,
',')))
383 pwnl = strlen(pw->pw_name);
387 if (dest[
idx] ==
'&')
389 memmove(&dest[
idx + pwnl], &dest[
idx + 1],
390 MAX((ssize_t)(destlen -
idx - pwnl - 1), 0));
391 memcpy(&dest[
idx], pw->pw_name,
MIN(destlen -
idx - 1, pwnl));
392 dest[
idx] = toupper((
unsigned char) dest[
idx]);
468 const char *suffix,
const char *src,
int line)
495 const char *suffix,
const char *src,
int line)
498 snprintf(buf, buflen,
"%s/%s-%s-%d-%d-%" PRIu64
"%s%s",
NONULL(
C_Tmpdir),
504 "%s:%d: ERROR: insufficient buffer space to hold temporary "
505 "filename! buflen=%zu but need %zu\n",
506 src, line, buflen, n);
509 if ((unlink(buf) != 0) && (errno != ENOENT))
512 line, buf, strerror(errno), errno);
528 char *p = buf, *q = buf;
547 p = strchr(buf,
':') + 1;
549 q = strchr(p + 2,
'/');
556 if (strstr(p,
"//") || strstr(p,
"/./"))
562 if ((p[0] ==
'/') && (p[1] ==
'/'))
567 else if ((p[0] ==
'/') && (p[1] ==
'.') && (p[2] ==
'/'))
577 else if (strstr(p,
"..") && ((scheme ==
U_UNKNOWN) || (scheme ==
U_FILE)) &&
591 memmove(buf, buf + len - 1,
mutt_str_len(buf + len - 1) + 1);
601 if (!buf || !buf->
data)
631 if (S_ISDIR(st.st_mode))
640 (
_(
"File is a directory, save under it: (y)es, (n)o, (a)ll?"),
_(
"yna")))
659 return (ans ==
MUTT_NO) ? 1 : -1;
664 false, NULL, NULL, NULL) != 0) ||
713 char *p = strpbrk(buf,
"%@");
735 char *p = strpbrk(dest->
data,
"%@");
758 for (
char *p = dest->
data; *p; p++)
777 char prefix[128], tmp[1024];
778 char *cp = NULL, *wptr = buf;
780 char if_str[128], else_str[128];
781 size_t wlen, count, len, wid;
782 FILE *fp_filter = NULL;
783 char *recycler = NULL;
802 if ((n > 1) && (src[n - 1] ==
'|'))
806 while ((off > 0) && (src[off - 2] ==
'\\'))
812 if ((off > 0) && (((n - off) % 2) == 0))
819 strncpy(srccopy, src, n);
820 srccopy[n - 1] =
'\0';
843 for (
char *p = tmp; p && (*p !=
'\0'); p++)
869 n = fread(buf, 1, buflen , fp_filter);
877 while ((n > 0) && ((buf[n - 1] ==
'\n') || (buf[n - 1] ==
'\r')))
885 if ((n > 0) && (buf[n - 1] ==
'%'))
889 if ((n > 0) && (buf[n - 1] !=
'%'))
899 callback,
data, flags);
909 strerror(errno), errno);
926 while (*src && (wlen < buflen))
943 char *p = (
char *) src;
946 for (; *p && (*p !=
'?'); p++)
953 for (; *p && (*p !=
'?'); p++)
956 if ((*p ==
'<') || (*p ==
'>'))
974 while ((count <
sizeof(prefix)) && (*src !=
'?'))
988 while ((count <
sizeof(prefix)) && (isdigit((
unsigned char) *src) || (*src ==
'.') ||
989 (*src ==
'-') || (*src ==
'=')))
1014 while ((lrbalance > 0) && (count <
sizeof(if_str)) && *src)
1016 if ((src[0] ==
'%') && (src[1] ==
'>'))
1030 else if ((src[0] ==
'%') && (src[1] ==
'<'))
1034 else if (src[0] ==
'>')
1040 if ((lrbalance == 1) && (src[0] ==
'&'))
1052 while ((lrbalance > 0) && (count <
sizeof(else_str)) && (*src !=
'\0'))
1054 if ((src[0] ==
'%') && (src[1] ==
'>'))
1068 else if ((src[0] ==
'%') && (src[1] ==
'<'))
1072 else if (src[0] ==
'>')
1078 if ((lrbalance == 1) && (src[0] ==
'&'))
1092 if ((ch ==
'>') || (ch ==
'*'))
1096 int soft = ch ==
'*';
1106 if (((col < cols) && (wlen < buflen)) || soft)
1115 pad = (cols - col - wid) / pw;
1120 if (wlen + (
pad * pl) + len > buflen)
1121 pad = (buflen > (wlen + len)) ? ((buflen - wlen - len) / pl) : 0;
1126 while (((col + (
pad * pw) + wid) < cols) && ((wlen + (
pad * pl) + len) < buflen))
1135 memcpy(wptr, src, pl);
1146 int avail_cols = (cols > offset) ? (cols - offset) : 0;
1156 while (((col + wid) < avail_cols) && ((wlen + len) < buflen))
1163 if ((len + wlen) > buflen)
1165 memcpy(wptr, tmp, len);
1182 if ((col < cols) && (wlen < buflen))
1184 int c = (cols - col) / pw;
1185 if ((c > 0) && ((wlen + (c * pl)) > buflen))
1186 c = ((signed) (buflen - wlen)) / pl;
1189 memcpy(wptr, src, pl);
1200 bool to_lower =
false;
1201 bool no_dots =
false;
1203 while ((ch ==
'_') || (ch ==
':'))
1215 src = callback(tmp,
sizeof(tmp), col, cols, ch, src, prefix, if_str,
1216 else_str,
data, flags);
1229 if ((len + wlen) > buflen)
1232 memcpy(wptr, tmp, len);
1238 else if (*src ==
'\\')
1278 if ((bytes > 0) && ((wlen + bytes) < buflen))
1280 memcpy(wptr, src, bytes);
1288 src += buflen - wlen;
1317 if (path[len - 1] ==
'|')
1330 if (stat(path, &s) < 0)
1332 if (S_ISDIR(s.st_mode))
1337 fp = fopen(path,
"r");
1360 mutt_error(
_(
"Can't save message to POP mailbox"));
1383 mutt_error(
_(
"Can't save message to news server"));
1388 if (stat(s, st) != -1)
1402 if (errno == ENOENT)
1464 static char vstring[256];
1465 snprintf(vstring,
sizeof(vstring),
"NeoMutt %s%s", PACKAGE_VERSION,
GitVer);
1483 for (
size_t i = 0; i < len; i++)
1485 if (!isalnum(buf->
data[i]) && !strchr(
"/.-_", buf->
data[i]))
1509 while ((token = strsep(&xdg,
":")))
1556 if (buf[n - 1] ==
'/')
1560 for (n--; ((n >= 0) && (buf[n] !=
'/')); n--)
1598 if ((a[0] ==
'+') && (b[0] ==
'+'))
1605 const char *a_end = strrchr(a,
'/');
1606 const char *b_end = strrchr(b,
'/');
1609 if ((!a_end) ^ (!b_end))
1617 size_t a_len = a_end - a;
1618 size_t b_len = b_end - b;
1619 size_t min =
MIN(a_len, b_len);
1620 int same = (a[min] ==
'/') && (b[min] ==
'/') && (a[min + 1] !=
'\0') &&
1648 for (; *path; path++)
1665 if (!buf || (buflen == 0))
1670 snprintf(buf, buflen,
"%d", (
int) num);
1679 (num < 103) ? 0.1 : (num / 1024.0));
1684 snprintf(buf, buflen,
C_SizeUnitsOnLeft ? (
"K%zu") : (
"%zuK"), (num + 51) / 1024);
1688 snprintf(buf, buflen,
C_SizeUnitsOnLeft ?
"M%3.1f" :
"%3.1fM", num / 1048576.0);
1693 snprintf(buf, buflen,
C_SizeUnitsOnLeft ? (
"M%zu") : (
"%zuM"), (num + 52428) / 1048576);
1707 if (!str || (*str ==
'\0'))
1735 struct ListNode *np = NULL, *tmp = NULL;
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to 'us-ascii'.
void mutt_endwin(void)
Shutdown curses/slang.
FILE * mutt_open_read(const char *path, pid_t *thepid)
Run a command to read from.
QuadOption
Possible values for a quad-option.
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
static int pad(FILE *fp, int col, int i)
Write some padding to a file.
struct MuttWindow * MessageWindow
Message Window, ":set", etc.
WHERE bool C_SizeUnitsOnLeft
Config: Show the units as a prefix to the size.
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
@ XDG_CONFIG_DIRS
XDG system dir: /etc/xdg.
String manipulation buffer.
@ LL_DEBUG3
Log at debug level 3.
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
void mutt_buffer_seek(struct Buffer *buf, size_t offset)
set current read/write position to offset from beginning
#define STAILQ_REMOVE(head, elm, type, field)
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
void mutt_save_path(char *buf, size_t buflen, const struct Address *addr)
Turn an email address into a filename (for saving)
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
WHERE short C_SleepTime
Config: Time to pause after certain info messages.
#define MUTT_ICONV_NO_FLAGS
No flags are set.
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
UrlScheme
All recognised Url types.
@ U_UNKNOWN
Url wasn't recognised.
@ MUTT_POP
'POP3' Mailbox type
int mutt_file_sanitize_regex(struct Buffer *dest, const char *src)
Escape any regex-magic characters in a string.
#define mutt_buffer_mktemp(buf)
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
#define TAILQ_EMPTY(head)
Cached regular expression.
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
char * mutt_str_dup(const char *str)
Copy a string, safely.
@ LL_DEBUG1
Log at debug level 1.
int mutt_strwidth(const char *s)
Measure a string's width in screen cells.
#define mutt_buffer_mktemp_pfx_sfx(buf, prefix, suffix)
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
char * dptr
Current read/write position.
@ MUTT_MAILBOX_ERROR
Error occurred examining Mailbox.
size_t dsize
Length of data.
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
@ LL_DEBUG5
Log at debug level 5.
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
void mutt_sleep(short s)
Sleep for a while.
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
char * mutt_expand_path_regex(char *buf, size_t buflen, bool regex)
Create the canonical path (with regex char escaping)
void mutt_mktemp_full(char *buf, size_t buflen, const char *prefix, const char *suffix, const char *src, int line)
Create a temporary filename.
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
struct Email * email_new(void)
Create a new Email.
char * subtype
content-type subtype
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
#define STAILQ_FOREACH(var, head, field)
const char filename_safe_chars[]
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
SaveAttach
Options for saving attachments.
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
static const char * xdg_env_vars[]
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
WHERE bool C_SaveAddress
Config: Use sender's full address as a default save folder.
void mutt_buffer_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
#define MUTT_FILE
Do file completion.
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
const char * mutt_path_basename(const char *f)
Find the last component for a pathname.
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
void mutt_buffer_save_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
#define APPLICATION_PGP
Use PGP to encrypt/sign.
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
WHERE char * LastFolder
Previously selected mailbox.
WHERE bool C_SizeShowMb
Config: Show sizes in megabytes for sizes greater than 1 megabyte.
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
@ U_IMAPS
Url is imaps://.
WHERE bool C_ArrowCursor
Config: Use an arrow '->' instead of highlighting in the index.
void mutt_safe_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
@ MUTT_IMAP
'IMAP' Mailbox type
void mutt_default_save(char *path, size_t pathlen, struct Email *e)
Find the default save path for an email.
struct AddressList to
Email's 'To' list.
@ TYPE_MESSAGE
Type: 'message/*'.
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
struct Envelope * env
Envelope information.
@ MUTT_SAVE_APPEND
Append to existing file.
uint64_t mutt_rand64(void)
Create a 64-bit random number.
#define mutt_debug(LEVEL,...)
@ MUTT_NO
User answered 'No', or assume 'No'.
char * C_Tmpdir
Config: Directory for temporary files.
WHERE bool C_SizeShowFractions
Config: Show size fractions with a single decimal place.
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
const char * mutt_str_getenv(const char *name)
Get an environment variable.
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
struct Regex * C_GecosMask
Config: Regex for parsing GECOS field of /etc/passwd.
struct Envelope * mutt_env_new(void)
Create a new Envelope.
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
int mutt_inbox_cmp(const char *a, const char *b)
do two folders share the same path and one is an inbox
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
WHERE char * C_Record
Config: Folder to save 'sent' messages.
WHERE bool C_SizeShowBytes
Config: Show smaller sizes in bytes.
char * mailbox
Mailbox and host address.
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.
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
int mutt_set_xdg_path(enum XdgType type, struct Buffer *buf)
Find an XDG path or its fallback.
struct AddressList from
Email's 'From' list.
@ TYPE_APPLICATION
Type: 'application/*'.
char * HomeDir
User's home directory.
void mutt_buffer_mktemp_full(struct Buffer *buf, const char *prefix, const char *suffix, const char *src, int line)
Create a temporary file.
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string.
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.
int mutt_mb_charlen(const char *s, int *width)
Count the bytes in a (multibyte) character.
WHERE char * ShortHostname
Short version of the hostname.
@ TYPE_TEXT
Type: 'text/*'.
struct AddressList * alias_lookup(const char *name)
Find an Alias.
XdgType
XDG variable types.
@ MUTT_SAVE_NO_FLAGS
No flags set.
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
WHERE char * C_SpoolFile
Config: Inbox.
void remove_from_stailq(struct ListHead *head, const char *str)
Remove an item, matching a string, from a List.
unsigned int type
content-type primary type, ContentType
WHERE char * C_Mbox
Config: Folder that receives read emails (see Move)
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user's real name in /etc/passwd.
@ U_NOTMUCH
Url is notmuch://.
MailboxType
Supported mailbox formats.
#define MUTT_CLEAR
Clear input if printable character is pressed.
WHERE char * CurrentFolder
Currently selected mailbox.
WHERE char * C_ArrowString
Config: Use an custom string for arrow_cursor.
void email_free(struct Email **ptr)
Free an Email.
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
bool mutt_istrn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings ignoring case (to a maximum), safely.
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
@ XDG_CONFIG_HOME
XDG home dir: ~/.config.
@ MUTT_SAVE_OVERWRITE
Overwrite existing file.
char * C_Charset
Config: Default character set for displaying text on screen.
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
void mutt_get_parent_path(const char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
char * data
Pointer to data.
@ TYPE_MULTIPART
Type: 'multipart/*'.
The envelope/body of an email.
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
const char * mutt_make_version(void)
Generate the NeoMutt version string.
void mutt_buffer_sanitize_filename(struct Buffer *buf, const char *path, short slash)
Replace unsafe characters in a filename.
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
WHERE bool C_ConfirmAppend
Config: Confirm before appending emails to a mailbox.
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
WHERE bool C_ConfirmCreate
Config: Confirm before creating a new mailbox.
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
static const char * xdg_defaults[]
int imap_expand_path(struct Buffer *buf)
Buffer wrapper around imap_path_canon()
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final '/'.
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)