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')))
104 if ((lstat(
mutt_b2s(buf), &sb) == -1) && (errno == ENOENT))
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);
294 if (regex && *(
mutt_b2s(p)) && !recurse)
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);
385 for (
int idx = 0; dest[idx]; idx++)
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)
475 if (unlink(
mutt_b2s(buf)) && (errno != ENOENT))
478 line,
mutt_b2s(buf), strerror(errno), errno);
494 const char *suffix,
const char *src,
int line)
497 snprintf(buf, buflen,
"%s/%s-%s-%d-%d-%" PRIu64
"%s%s",
NONULL(
C_Tmpdir),
503 "%s:%d: ERROR: insufficient buffer space to hold temporary " 504 "filename! buflen=%zu but need %zu\n",
505 src, line, buflen, n);
508 if ((unlink(buf) != 0) && (errno != ENOENT))
511 line, buf, strerror(errno), errno);
527 char *p = buf, *q = buf;
546 p = strchr(buf,
':') + 1;
548 q = strchr(p + 2,
'/');
555 if (strstr(p,
"//") || strstr(p,
"/./"))
561 if ((p[0] ==
'/') && (p[1] ==
'/'))
566 else if ((p[0] ==
'/') && (p[1] ==
'.') && (p[2] ==
'/'))
576 else if (strstr(p,
"..") && ((scheme ==
U_UNKNOWN) || (scheme ==
U_FILE)) &&
590 memmove(buf, buf + len - 1,
mutt_str_len(buf + len - 1) + 1);
600 if (!buf || !buf->
data)
626 if (access(
mutt_b2s(fname), F_OK) != 0)
628 if (stat(
mutt_b2s(fname), &st) != 0)
630 if (S_ISDIR(st.st_mode))
639 (
_(
"File is a directory, save under it: (y)es, (n)o, (a)ll?"),
_(
"yna")))
658 return (ans ==
MUTT_NO) ? 1 : -1;
711 char *p = strpbrk(buf,
"%@");
733 char *p = strpbrk(dest->
data,
"%@");
756 for (
char *p = dest->
data; *p; p++)
775 char prefix[128], tmp[1024];
776 char *cp = NULL, *wptr = buf;
778 char if_str[128], else_str[128];
779 size_t wlen, count, len, wid;
780 FILE *fp_filter = NULL;
781 char *recycler = NULL;
800 if ((n > 1) && (src[n - 1] ==
'|'))
804 while ((off > 0) && (src[off - 2] ==
'\\'))
810 if ((off > 0) && (((n - off) % 2) == 0))
817 strncpy(srccopy, src, n);
818 srccopy[n - 1] =
'\0';
840 data, flags | MUTT_FORMAT_NOFILTER);
841 for (
char *p = tmp; p && (*p !=
'\0'); p++)
867 n = fread(buf, 1, buflen , fp_filter);
875 while ((n > 0) && ((buf[n - 1] ==
'\n') || (buf[n - 1] ==
'\r')))
883 if ((n > 0) && (buf[n - 1] ==
'%'))
887 if ((n > 0) && (buf[n - 1] !=
'%'))
897 callback, data, flags);
907 strerror(errno), errno);
924 while (*src && (wlen < buflen))
941 char *p = (
char *) src;
944 for (; *p && (*p !=
'?'); p++)
951 for (; *p && (*p !=
'?'); p++)
954 if ((*p ==
'<') || (*p ==
'>'))
972 while ((count <
sizeof(prefix)) && (*src !=
'?'))
986 while ((count <
sizeof(prefix)) && (isdigit((
unsigned char) *src) || (*src ==
'.') ||
987 (*src ==
'-') || (*src ==
'=')))
1012 while ((lrbalance > 0) && (count <
sizeof(if_str)) && *src)
1014 if ((src[0] ==
'%') && (src[1] ==
'>'))
1028 else if ((src[0] ==
'%') && (src[1] ==
'<'))
1032 else if (src[0] ==
'>')
1038 if ((lrbalance == 1) && (src[0] ==
'&'))
1050 while ((lrbalance > 0) && (count <
sizeof(else_str)) && (*src !=
'\0'))
1052 if ((src[0] ==
'%') && (src[1] ==
'>'))
1066 else if ((src[0] ==
'%') && (src[1] ==
'<'))
1070 else if (src[0] ==
'>')
1076 if ((lrbalance == 1) && (src[0] ==
'&'))
1090 if ((ch ==
'>') || (ch ==
'*'))
1094 int soft = ch ==
'*';
1104 if (((col < cols) && (wlen < buflen)) || soft)
1113 pad = (cols - col - wid) / pw;
1118 if (wlen + (pad * pl) + len > buflen)
1119 pad = (buflen > (wlen + len)) ? ((buflen - wlen - len) / pl) : 0;
1124 while (((col + (pad * pw) + wid) < cols) && ((wlen + (pad * pl) + len) < buflen))
1133 memcpy(wptr, src, pl);
1144 int avail_cols = (cols > offset) ? (cols - offset) : 0;
1154 while (((col + wid) < avail_cols) && ((wlen + len) < buflen))
1161 if ((len + wlen) > buflen)
1163 memcpy(wptr, tmp, len);
1180 if ((col < cols) && (wlen < buflen))
1182 int c = (cols - col) / pw;
1183 if ((c > 0) && ((wlen + (c * pl)) > buflen))
1184 c = ((signed) (buflen - wlen)) / pl;
1187 memcpy(wptr, src, pl);
1198 bool to_lower =
false;
1199 bool no_dots =
false;
1201 while ((ch ==
'_') || (ch ==
':'))
1213 src = callback(tmp,
sizeof(tmp), col, cols, ch, src, prefix, if_str,
1214 else_str, data, flags);
1227 if ((len + wlen) > buflen)
1230 memcpy(wptr, tmp, len);
1236 else if (*src ==
'\\')
1276 if ((bytes > 0) && ((wlen + bytes) < buflen))
1278 memcpy(wptr, src, bytes);
1286 src += buflen - wlen;
1315 if (path[len - 1] ==
'|')
1328 if (stat(path, &s) < 0)
1330 if (S_ISDIR(s.st_mode))
1335 fp = fopen(path,
"r");
1358 mutt_error(
_(
"Can't save message to POP mailbox"));
1381 mutt_error(
_(
"Can't save message to news server"));
1386 if (stat(s, st) != -1)
1400 if (errno == ENOENT)
1462 static char vstring[256];
1463 snprintf(vstring,
sizeof(vstring),
"NeoMutt %s%s", PACKAGE_VERSION,
GitVer);
1481 for (
size_t i = 0; i < len; i++)
1483 if (!isalnum(buf->
data[i]) && !strchr(
"/.-_", buf->
data[i]))
1507 while ((token = strsep(&xdg,
":")))
1512 if (access(
mutt_b2s(buf), F_OK) == 0)
1521 if (access(
mutt_b2s(buf), F_OK) == 0)
1554 if (buf[n - 1] ==
'/')
1558 for (n--; ((n >= 0) && (buf[n] !=
'/')); n--)
1596 if ((a[0] ==
'+') && (b[0] ==
'+'))
1601 const char *a_end = strrchr(a,
'/');
1602 const char *b_end = strrchr(b,
'/');
1605 if ((!a_end) ^ (!b_end))
1613 size_t a_len = a_end - a;
1614 size_t b_len = b_end - b;
1615 size_t min =
MIN(a_len, b_len);
1616 int same = (a[min] ==
'/') && (b[min] ==
'/') && (a[min + 1] !=
'\0') &&
1644 for (; *path; path++)
1661 if (!buf || (buflen == 0))
1666 snprintf(buf, buflen,
"%d", (
int) num);
1675 (num < 103) ? 0.1 : (num / 1024.0));
1680 snprintf(buf, buflen,
C_SizeUnitsOnLeft ? (
"K%zu") : (
"%zuK"), (num + 51) / 1024);
1684 snprintf(buf, buflen,
C_SizeUnitsOnLeft ?
"M%3.1f" :
"%3.1fM", num / 1048576.0);
1689 snprintf(buf, buflen,
C_SizeUnitsOnLeft ? (
"M%zu") : (
"%zuM"), (num + 52428) / 1048576);
1703 if (!str || (*str ==
'\0'))
1731 struct ListNode *np = NULL, *tmp = NULL;
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Convenience wrapper for the gui headers.
WHERE bool C_SizeUnitsOnLeft
Config: Show the units as a prefix to the size.
#define mutt_buffer_mktemp(buf)
#define STAILQ_REMOVE(head, elm, type, field)
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
The envelope/body of an email.
#define MUTT_CLEAR
Clear input if printable character is pressed.
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe()
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
'NNTP' (Usenet) Mailbox type
Structs that make up an email.
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
const char * mutt_path_basename(const char *f)
Find the last component for a pathname.
#define mutt_buffer_mktemp_pfx_sfx(buf, prefix, suffix)
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
String manipulation buffer.
WHERE short C_SleepTime
Config: Time to pause after certain info messages.
char * mutt_str_dup(const char *str)
Copy a string, safely.
Url wasn't recognised.
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final '/'.
Mailbox wasn't recognised.
Error occurred examining Mailbox.
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
char * mailbox
Mailbox and host address.
void mutt_buffer_save_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
int mutt_mb_charlen(const char *s, int *width)
Count the bytes in a (multibyte) character.
void mutt_default_save(char *path, size_t pathlen, struct Email *e)
Find the default save path for an email.
static const char * xdg_env_vars[]
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
QuadOption
Possible values for a quad-option.
Convenience wrapper for the config headers.
char * HomeDir
User's home directory.
const char * mutt_str_getenv(const char *name)
Get an environment variable.
void mutt_buffer_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
bool mutt_istrn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings ignoring case (to a maximum), safely.
Some miscellaneous functions.
char * mutt_expand_path_regex(char *buf, size_t buflen, bool regex)
Create the canonical path (with regex char escaping)
size_t dsize
Length of data.
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
void mutt_sleep(short s)
Sleep for a while.
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
int imap_expand_path(struct Buffer *buf)
Buffer wrapper around imap_path_canon()
void mutt_mktemp_full(char *buf, size_t buflen, const char *prefix, const char *suffix, const char *src, int line)
Create a temporary filename.
Parse and execute user-defined hooks.
Many unsorted constants and some structs.
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
UrlScheme
All recognised Url types.
struct AddressList from
Email's 'From' list.
struct AddressList * alias_lookup(const char *name)
Find an Alias.
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
struct Envelope * env
Envelope information.
Convenience wrapper for the core headers.
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
User aborted the question (with Ctrl-G)
struct Envelope * mutt_env_new(void)
Create a new Envelope.
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
char * mutt_str_lower(char *s)
Convert all characters in the string to lowercase.
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
void mutt_safe_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
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.
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
int mutt_file_sanitize_regex(struct Buffer *dest, const char *src)
Escape any regex-magic characters in a string.
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Prototypes for many functions.
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
WHERE bool C_SizeShowBytes
Config: Show smaller sizes in bytes.
#define APPLICATION_PGP
Use PGP to encrypt/sign.
'POP3' Mailbox type
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
struct MuttWindow * MessageWindow
Message Window, ":set", etc.
void mutt_endwin(void)
Shutdown curses/slang.
WHERE bool C_SaveAddress
Config: Use sender's full address as a default save folder.
uint64_t mutt_rand64(void)
Create a 64-bit random number.
int mutt_strwidth(const char *s)
Measure a string's width in screen cells.
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
XdgType
XDG variable types.
struct Regex * C_GecosMask
Config: Regex for parsing GECOS field of /etc/passwd.
char * dptr
Current read/write position.
WHERE char * ShortHostname
Short version of the hostname.
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
int mutt_inbox_cmp(const char *a, const char *b)
do two folders share the same path and one is an inbox
char * data
Pointer to data.
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
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.
API for encryption/signing of emails.
WHERE bool C_SizeShowFractions
Config: Show size fractions with a single decimal place.
WHERE bool C_Confirmcreate
Config: Confirm before creating a new mailbox.
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
#define STAILQ_FOREACH(var, head, field)
WHERE bool C_SizeShowMb
Config: Show sizes in megabytes for sizes greater than 1 megabyte.
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
WHERE char * LastFolder
Previously selected mailbox.
#define MUTT_FILE
Do file completion.
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
unsigned int type
content-type primary type, ContentType
'Notmuch' (virtual) Mailbox type
WHERE bool C_ArrowCursor
Config: Use an arrow '->' instead of highlighting in the index.
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_set_xdg_path(enum XdgType type, struct Buffer *buf)
Find an XDG path or its fallback.
#define mutt_buffer_get_field(field, buf, complete)
Type: 'message/*'.
bool mutt_strn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings (to a maximum), safely.
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
WHERE char * C_Record
Config: Folder to save 'sent' messages.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
void remove_from_stailq(struct ListHead *head, const char *str)
Remove an item, matching a string, from a List.
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
void mutt_buffer_mktemp_full(struct Buffer *buf, const char *prefix, const char *suffix, const char *src, int line)
Create a temporary file.
Type: 'multipart/*'.
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
MailboxType
Supported mailbox formats.
WHERE char * C_Spoolfile
Config: Inbox.
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user's real name in /etc/passwd.
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
void mutt_buffer_sanitize_filename(struct Buffer *buf, const char *path, short slash)
Replace unsafe characters in a filename.
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Cached regular expression.
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.
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
char * C_Tmpdir
Config: Directory for temporary files.
WHERE char * CurrentFolder
Currently selected mailbox.
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
const char filename_safe_chars[]
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
User answered 'No', or assume 'No'.
struct AddressList to
Email's 'To' list.
struct Email * email_new(void)
Create a new Email.
Hundreds of global variables to back the user variables.
#define mutt_debug(LEVEL,...)
#define TAILQ_EMPTY(head)
Convenience wrapper for the library headers.
void email_free(struct Email **ptr)
Free an Email.
FILE * mutt_open_read(const char *path, pid_t *thepid)
Run a command to read from.
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
XDG system dir: /etc/xdg.
static const char * xdg_defaults[]
'IMAP' Mailbox type
char * C_Charset
Config: Default character set for displaying text on screen.
WHERE char * C_Mbox
Config: Folder that receives read emails (see Move)
void mutt_get_parent_path(const char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
static int pad(FILE *fp, int col, int i)
Write some padding to a file.
Type: 'application/*'.
WHERE char * C_ArrowString
Config: Use an custom string for arrow_cursor.
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to 'us-ascii'.
SaveAttach
Options for saving attachments.
const char * mutt_make_version(void)
Generate the NeoMutt version string.
User answered 'Yes', or assume 'Yes'.
void mutt_save_path(char *buf, size_t buflen, const struct Address *addr)
Turn an email address into a filename (for saving)
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
WHERE bool C_Confirmappend
Config: Confirm before appending emails to a mailbox.