89 if (!(buf->
data && (buf->
data[0] !=
'\0')))
101 struct stat st = { 0 };
102 if ((lstat(
buf_string(buf), &st) == -1) && (errno == ENOENT))
105 char *suffix = strchr(prefix->
data,
'.');
140 const char *s = NULL;
141 const char *tail =
"";
143 bool recurse =
false;
158 if ((s[1] ==
'/') || (s[1] ==
'\0'))
165 char *t = strchr(s + 1,
'/');
169 struct passwd *pw = getpwnam(s + 1);
202 if ((mb_type ==
MUTT_IMAP) && ((c_folder[strlen(c_folder) - 1] ==
'}') ||
203 (c_folder[strlen(c_folder) - 1] ==
'/')))
211 else if (c_folder && (c_folder[strlen(c_folder) - 1] ==
'/'))
376 regmatch_t pat_match[1];
380 if (!pw || !pw->pw_gecos)
383 memset(dest, 0, destlen);
389 MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
391 else if ((p = strchr(pw->pw_gecos,
',')))
400 pwnl = strlen(pw->pw_name);
402 for (
int idx = 0; dest[idx]; idx++)
404 if (dest[idx] ==
'&')
406 memmove(&dest[idx + pwnl], &dest[idx + 1],
407 MAX((ssize_t) (destlen - idx - pwnl - 1), 0));
408 memcpy(&dest[idx], pw->pw_name,
MIN(destlen - idx - 1, pwnl));
409 dest[idx] = toupper((
unsigned char) dest[idx]);
488 char *p = buf, *q = buf;
508 p = strchr(buf,
':') + 1;
510 q = strchr(p + 2,
'/');
517 if (strstr(p,
"//") || strstr(p,
"/./"))
523 if ((p[0] ==
'/') && (p[1] ==
'/'))
528 else if ((p[0] ==
'/') && (p[1] ==
'.') && (p[2] ==
'/'))
540 else if (strstr(p,
"..") && ((scheme ==
U_UNKNOWN) || (scheme ==
U_FILE)) &&
554 memmove(buf, buf + len - 1,
mutt_str_len(buf + len - 1) + 1);
564 if (!buf || !buf->
data)
587 struct stat st = { 0 };
594 if (S_ISDIR(st.st_mode))
603 (
_(
"File is a directory, save under it: (y)es, (n)o, (a)ll?"),
_(
"yna")))
622 return (ans ==
MUTT_NO) ? 1 : -1;
640 char buf[4096] = { 0 };
641 snprintf(buf,
sizeof(buf),
"%s - %s",
buf_string(fname),
643 _(
"File exists, (o)verwrite, (a)ppend, or (c)ancel?"));
679 char *p = strpbrk(buf,
"%@");
704 char *p = strpbrk(dest->
data,
"%@");
729 for (
char *p = dest->
data; *p; p++)
730 if ((*p ==
'/') || isspace(*p) || !
IsPrint((
unsigned char) *p))
748 char prefix[128], tmp[1024];
749 char *cp = NULL, *wptr = buf;
751 char if_str[128], else_str[128];
752 size_t wlen, count, len, wid;
753 FILE *fp_filter = NULL;
754 char *recycler = NULL;
775 if ((n > 1) && (src[n - 1] ==
'|'))
779 while ((off > 0) && (src[off - 2] ==
'\\'))
785 if ((off > 0) && (((n - off) % 2) == 0))
787 char srccopy[1024] = { 0 };
792 strncpy(srccopy, src, n);
793 srccopy[n - 1] =
'\0';
816 for (
char *p = tmp; p && (*p !=
'\0'); p++)
844 n = fread(buf, 1, buflen , fp_filter);
852 while ((n > 0) && ((buf[n - 1] ==
'\n') || (buf[n - 1] ==
'\r')))
860 if ((n > 0) && (buf[n - 1] ==
'%'))
864 if ((n > 0) && (buf[n - 1] !=
'%'))
874 callback,
data, flags);
884 strerror(errno), errno);
901 while (*src && (wlen < buflen))
918 char *p = (
char *) src;
921 for (; *p && (*p !=
'?'); p++)
928 for (; *p && (*p !=
'?'); p++)
931 if ((*p ==
'<') || (*p ==
'>'))
949 while ((count < (
sizeof(prefix) - 1)) && (*src !=
'\0') && (*src !=
'?'))
958 flags &= ~MUTT_FORMAT_OPTIONAL;
963 while ((count < (
sizeof(prefix) - 1)) && strchr(
"0123456789.-=", *src))
988 while ((lrbalance > 0) && (count <
sizeof(if_str)) && *src)
990 if ((src[0] ==
'%') && (src[1] ==
'>'))
1004 else if ((src[0] ==
'%') && (src[1] ==
'<'))
1008 else if (src[0] ==
'>')
1014 if ((lrbalance == 1) && (src[0] ==
'&'))
1026 while ((lrbalance > 0) && (count <
sizeof(else_str)) && (*src !=
'\0'))
1028 if ((src[0] ==
'%') && (src[1] ==
'>'))
1042 else if ((src[0] ==
'%') && (src[1] ==
'<'))
1046 else if (src[0] ==
'>')
1052 if ((lrbalance == 1) && (src[0] ==
'&'))
1066 if ((ch ==
'>') || (ch ==
'*'))
1070 int soft = ch ==
'*';
1080 if (((col < cols) && (wlen < buflen)) || soft)
1089 pad = (cols - col - wid) / pw;
1094 if (wlen + (
pad * pl) + len > buflen)
1096 pad = (buflen > (wlen + len)) ? ((buflen - wlen - len) / pl) : 0;
1102 while (((col + (
pad * pw) + wid) < cols) && ((wlen + (
pad * pl) + len) < buflen))
1111 memcpy(wptr, src, pl);
1122 int avail_cols = (cols > offset) ? (cols - offset) : 0;
1132 while (((col + wid) < avail_cols) && ((wlen + len) < buflen))
1139 if ((len + wlen) > buflen)
1141 memcpy(wptr, tmp, len);
1158 if ((col < cols) && (wlen < buflen))
1160 int c = (cols - col) / pw;
1161 if ((c > 0) && ((wlen + (c * pl)) > buflen))
1162 c = ((signed) (buflen - wlen)) / pl;
1165 memcpy(wptr, src, pl);
1176 bool to_lower =
false;
1177 bool no_dots =
false;
1179 while ((ch ==
'_') || (ch ==
':'))
1191 src = callback(tmp,
sizeof(tmp), col, cols, ch, src, prefix, if_str,
1192 else_str,
data, flags);
1205 if ((len + wlen) > buflen)
1208 memcpy(wptr, tmp, len);
1214 else if (*src ==
'\\')
1254 if ((bytes > 0) && ((wlen + bytes) < buflen))
1256 memcpy(wptr, src, bytes);
1264 src += buflen - wlen;
1285 struct stat st = { 0 };
1293 if (path[len - 1] ==
'|')
1306 if (stat(path, &st) < 0)
1308 if (S_ISDIR(st.st_mode))
1313 fp = fopen(path,
"r");
1336 mutt_error(
_(
"Can't save message to POP mailbox"));
1344 if (c_confirm_append)
1361 mutt_error(
_(
"Can't save message to news server"));
1366 if (stat(s, st) != -1)
1380 if (errno == ENOENT)
1383 if (c_confirm_create)
1431 if (c_sleep_time > s)
1432 sleep(c_sleep_time);
1445 static char vstring[256];
1446 snprintf(vstring,
sizeof(vstring),
"NeoMutt %s%s", PACKAGE_VERSION,
GitVer);
1464 for (
size_t i = 0; i < len; i++)
1466 if (!isalnum(buf->
data[i]) && !strchr(
"/.-_", buf->
data[i]))
1492 if (
buf_printf(buf,
"%s/%s/neomuttrc", token, PACKAGE) < 0)
1501 if (
buf_printf(buf,
"%s/%s/Muttrc", token, PACKAGE) < 0)
1542 if (buf[n - 1] ==
'/')
1546 for (n--; ((n >= 0) && (buf[n] !=
'/')); n--)
1586 if ((a[0] ==
'+') && (b[0] ==
'+'))
1593 const char *a_end = strrchr(a,
'/');
1594 const char *b_end = strrchr(b,
'/');
1597 if ((!a_end) ^ (!b_end))
1605 size_t a_len = a_end - a;
1606 size_t b_len = b_end - b;
1607 size_t min =
MIN(a_len, b_len);
1608 int same = (a[min] ==
'/') && (b[min] ==
'/') && (a[min + 1] !=
'\0') &&
1636 for (; *path; path++)
1653 if (!buf || (buflen == 0))
1661 if (c_size_show_bytes && (num < 1024))
1663 snprintf(buf, buflen,
"%d", (
int) num);
1667 mutt_str_copy(buf, c_size_units_on_left ?
"K0" :
"0K", buflen);
1669 else if (c_size_show_fractions && (num < 10189))
1671 snprintf(buf, buflen, c_size_units_on_left ?
"K%3.1f" :
"%3.1fK",
1672 (num < 103) ? 0.1 : (num / 1024.0));
1674 else if (!c_size_show_mb || (num < 1023949))
1677 snprintf(buf, buflen, c_size_units_on_left ? (
"K%zu") : (
"%zuK"), (num + 51) / 1024);
1679 else if (c_size_show_fractions && (num < 10433332))
1681 snprintf(buf, buflen, c_size_units_on_left ?
"M%3.1f" :
"%3.1fM", num / 1048576.0);
1686 snprintf(buf, buflen, c_size_units_on_left ? (
"M%zu") : (
"%zuM"), (num + 52428) / 1048576);
1700 if (!str || (*str ==
'\0'))
1730 struct ListNode *np = NULL, *tmp = NULL;
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
struct AddressList * alias_lookup(const char *name)
Find an Alias.
const struct CompleteOps CompleteMailboxOps
Auto-Completion of Files / Mailboxes.
Select a Mailbox from a list.
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
void buf_seek(struct Buffer *buf, size_t offset)
Set current read/write position to offset from beginning.
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
size_t buf_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Convenience wrapper for the config headers.
char * HomeDir
User's home directory.
const char * cc_charset(void)
Get the cached value of $charset.
Convenience wrapper for the core headers.
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
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.
void mutt_endwin(void)
Shutdown curses.
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
struct Email * email_new(void)
Create a new Email.
void email_free(struct Email **ptr)
Free an Email.
Structs that make up an email.
struct Envelope * mutt_env_new(void)
Create a new Envelope.
const char FilenameSafeChars[]
Set of characters <=0x7F that are safe to use in filenames.
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
int mutt_file_sanitize_regex(struct Buffer *dest, const char *src)
Escape any regex-magic characters in a string.
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, char **envlist)
Set up filter program.
char * LastFolder
Previously selected mailbox.
char * CurrentFolder
Currently selected mailbox.
char ** EnvList
Private copy of the environment variables.
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 -.
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
int mw_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question -.
#define mutt_debug(LEVEL,...)
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
int mutt_inbox_cmp(const char *a, const char *b)
Do two folders share the same path and one is an inbox -.
Convenience wrapper for the gui headers.
static int pad(FILE *fp, int col, int i)
Write some padding to a file.
Read/write command history from/to a file.
void mutt_default_save(char *path, size_t pathlen, struct Email *e)
Find the default save path for an email.
Parse and execute user-defined hooks.
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
int imap_expand_path(struct Buffer *path)
Buffer wrapper around imap_path_canon()
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
@ LL_DEBUG3
Log at debug level 3.
@ LL_DEBUG5
Log at debug level 5.
@ LL_DEBUG1
Log at debug level 1.
MailboxType
Supported mailbox formats.
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
@ MUTT_MAILBOX_ERROR
Error occurred examining Mailbox.
@ MUTT_POP
'POP3' Mailbox type
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
@ MUTT_IMAP
'IMAP' Mailbox type
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
int mutt_mb_charlen(const char *s, int *width)
Count the bytes in a (multibyte) character.
@ TYPE_MESSAGE
Type: 'message/*'.
@ TYPE_MULTIPART
Type: 'multipart/*'.
@ TYPE_APPLICATION
Type: 'application/*'.
@ TYPE_TEXT
Type: 'text/*'.
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Convenience wrapper for the library headers.
const char * mutt_path_basename(const char *path)
Find the last component for a pathname.
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final '/'.
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.
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
char * mutt_str_dup(const char *str)
Copy a string, safely.
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
const char * mutt_str_getenv(const char *name)
Get an environment variable.
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
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.
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
char * mutt_str_sep(char **stringp, const char *delim)
Find first occurrence of any of delim characters in *stringp.
Many unsorted constants and some structs.
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
SaveAttach
Options for saving attachments.
@ MUTT_SAVE_APPEND
Append to existing file.
@ MUTT_SAVE_OVERWRITE
Overwrite existing file.
@ MUTT_SAVE_NO_FLAGS
No flags set.
char * mutt_expand_path_regex(char *buf, size_t buflen, bool regex)
Create the canonical path (with regex char escaping)
void mutt_get_parent_path(const char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
void remove_from_stailq(struct ListHead *head, const char *str)
Remove an item, matching a string, from a List.
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user's real name in /etc/passwd.
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
void buf_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
const char * mutt_make_version(void)
Generate the NeoMutt version string.
void mutt_sleep(short s)
Sleep for a while.
void mutt_save_path(char *buf, size_t buflen, const struct Address *addr)
Turn an email address into a filename (for saving)
void buf_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
void buf_save_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
int mutt_set_xdg_path(enum XdgType type, struct Buffer *buf)
Find an XDG path or its fallback.
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
static const char * XdgEnvVars[]
Accepted XDG environment variables.
void buf_sanitize_filename(struct Buffer *buf, const char *path, short slash)
Replace unsafe characters in a filename.
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
void mutt_safe_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email 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.
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to 'us-ascii'.
static const char * XdgDefaults[]
XDG default locations.
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
FILE * mutt_open_read(const char *path, pid_t *thepid)
Run a command to read from.
Some miscellaneous functions.
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
API for encryption/signing of emails.
#define APPLICATION_PGP
Use PGP to encrypt/sign.
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Prototypes for many functions.
XdgType
XDG variable types.
@ XDG_CONFIG_HOME
XDG home dir: ~/.config.
@ XDG_CONFIG_DIRS
XDG system dir: /etc/xdg.
QuadOption
Possible values for a quad-option.
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
@ MUTT_NO
User answered 'No', or assume 'No'.
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
enum QuadOption query_yesorno_help(const char *prompt, enum QuadOption def, struct ConfigSubset *sub, const char *name)
Ask the user a Yes/No question offering help.
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
#define STAILQ_REMOVE(head, elm, type, field)
#define STAILQ_FOREACH(var, head, field)
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
#define TAILQ_EMPTY(head)
struct Buffer * mailbox
Mailbox and host address.
char * subtype
content-type subtype
unsigned int type
content-type primary type, ContentType
String manipulation buffer.
char * dptr
Current read/write position.
size_t dsize
Length of data.
char * data
Pointer to data.
The envelope/body of an email.
struct Envelope * env
Envelope information.
struct AddressList to
Email's 'To' list.
struct AddressList from
Email's 'From' list.
Input for the file completion function.
Container for Accounts, Notifications.
struct ConfigSubset * sub
Inherited config items.
Cached regular expression.
#define buf_mktemp_pfx_sfx(buf, prefix, suffix)
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
UrlScheme
All recognised Url types.
@ U_NOTMUCH
Url is notmuch://.
@ U_UNKNOWN
Url wasn't recognised.
@ U_IMAPS
Url is imaps://.