143 adata->locked =
true;
145 else if (retry && !excl)
169 adata->locked =
false;
187 char buf[8192] = { 0 };
188 char return_path[1024] = { 0 };
193 struct Email *e = NULL;
194 struct stat st = { 0 };
195 struct Progress *progress = NULL;
205 m->
size = st.st_size;
207 buf[
sizeof(buf) - 1] =
'\0';
212 snprintf(msg,
sizeof(msg),
_(
"Reading %s..."),
mailbox_path(m));
218 if (!fgets(buf,
sizeof(buf) - 1, adata->
fp))
226 loc = ftello(adata->
fp);
241 if (!fgets(buf,
sizeof(buf) - 1, adata->
fp))
248 return_path[0] =
'\0';
250 if (!
is_from(buf, return_path,
sizeof(return_path), &t))
265 loc = ftello(adata->
fp);
273 if ((tmploc > 0) && (tmploc < m->size))
297 loc = ftello(adata->
fp);
300 if (!fgets(buf,
sizeof(buf) - 1, adata->
fp))
358 struct stat st = { 0 };
359 char buf[8192], return_path[256];
360 struct Email *e_cur = NULL;
362 int count = 0,
lines = 0;
364 struct Progress *progress = NULL;
374 m->
size = st.st_size;
384 snprintf(msg,
sizeof(msg),
_(
"Reading %s..."),
mailbox_path(m));
388 loc = ftello(adata->
fp);
389 while ((fgets(buf,
sizeof(buf), adata->
fp)) && !
SigInt)
391 if (
is_from(buf, return_path,
sizeof(return_path), &t))
432 loc = ftello(adata->
fp);
438 if ((tmploc > 0) && (tmploc < m->
size))
453 else if (tmploc != m->
size)
464 if (e_cur->
lines == 0)
472 if (fgetc(adata->
fp) ==
'\n')
499 loc = ftello(adata->
fp);
548 bool (*cmp_headers)(
const struct Email *,
const struct Email *) = NULL;
549 struct Email **e_old = NULL;
551 bool msg_mod =
false;
624 for (
int i = 0; i < old_msg_count; i++)
647 for (j = i; j < old_msg_count; j++)
651 if (cmp_headers(m->
emails[i], e_old[j]))
659 for (j = 0; (j < i) && (j < old_msg_count); j++)
663 if (cmp_headers(m->
emails[i], e_old[j]))
694 for (
int j = 0; j < old_msg_count; j++)
739 char buf[BUFSIZ + 7] = { 0 };
750 bytes_read = pos % BUFSIZ;
755 while ((pos -= bytes_read) >= 0)
758 memcpy(buf + BUFSIZ, buf, 7);
763 bytes_read = fread(buf,
sizeof(
char), bytes_read, fp);
767 for (
int i = bytes_read; i >= 0; i--)
801 struct Email *e = NULL;
802 struct Envelope *tmp_envelope = NULL;
833 FILE *fp = fopen(path,
"rb");
853 struct utimbuf utimebuf;
854 struct stat st2 = { 0 };
863 utimebuf.actime = st->st_atime;
864 utimebuf.modtime = st->st_mtime;
869 if (!c_mail_check_recent && (utimebuf.actime >= utimebuf.modtime) &&
mbox_has_new(m))
871 utimebuf.actime = utimebuf.modtime - 1;
1049 struct stat st = { 0 };
1050 bool unlock =
false;
1051 bool modified =
false;
1056 (st.st_size == m->
size))
1061 if (st.st_size == m->
size)
1068 if (st.st_size > m->
size)
1089 char buf[1024] = { 0 };
1094 if (fgets(buf,
sizeof(buf), adata->
fp))
1174 struct Buffer *tempfile = NULL;
1175 char buf[32] = { 0 };
1177 bool unlink_tempfile =
false;
1178 bool need_sort =
false;
1181 struct stat st = { 0 };
1182 struct MUpdate *new_offset = NULL;
1183 struct MUpdate *old_offset = NULL;
1185 struct Progress *progress = NULL;
1207 mutt_error(
_(
"Fatal error! Could not reopen mailbox!"));
1237 if ((fd == -1) || !(fp = fdopen(fd,
"w")))
1242 unlink_tempfile =
true;
1247 unlink_tempfile =
true;
1262 mutt_error(
_(
"sync: mbox modified, but no modified messages (report this bug)"));
1284 snprintf(msg,
sizeof(msg),
_(
"Writing %s..."),
mailbox_path(m));
1288 for (i = first, j = 0; i < m->
msg_count; i++)
1295 old_offset[i - first].
valid =
true;
1317 new_offset[i - first].
hdr = ftello(fp) + offset;
1347 if (fputs(
"\n",
fp) == EOF)
1370 unlink_tempfile =
false;
1386 !fgets(buf,
sizeof(buf), adata->
fp) ||
1408 if (ferror(adata->
fp))
1413 m->
size = ftello(adata->
fp);
1414 if ((m->
size < 0) || (ftruncate(fileno(adata->
fp), m->
size) != 0))
1460 mutt_error(
_(
"Fatal error! Could not reopen mailbox!"));
1467 for (i = first, j = first; i < m->
msg_count; i++)
1484 if (c_check_mbox_size)
1498 if (tempfile && unlink_tempfile)
1502 if ((first >= 0) && old_offset)
1504 for (i = first; (i < m->
msg_count) && old_offset[i - first].valid; i++)
1567#ifdef HAVE_UTIMENSAT
1569 ts[0] = adata->
atime;
1571 utimensat(AT_FDCWD, m->path, ts, 0);
1617 if (fputc(
'\n', msg->
fp) == EOF)
1620 if ((fflush(msg->
fp) == EOF) || (fsync(fileno(msg->
fp)) == -1))
1660 if (S_ISDIR(st->st_mode))
1663 if (st->st_size == 0)
1666 FILE *
fp = fopen(path,
"r");
1671 while ((ch = fgetc(
fp)) != EOF)
1676 if ((ch !=
'\n') && (ch !=
'\r'))
1684 char tmp[256] = { 0 };
1685 if (fgets(tmp,
sizeof(tmp),
fp))
1695 if (!c_check_mbox_size)
1700#ifdef HAVE_UTIMENSAT
1704 utimensat(AT_FDCWD, path, ts, 0);
1706 struct utimbuf times;
1707 times.actime = st->st_atime;
1708 times.modtime = st->st_mtime;
1709 utime(path, ×);
1772 if ((fflush(msg->
fp) == EOF) || (fsync(fileno(msg->
fp)) == -1))
1796 struct stat st = { 0 };
1800 bool new_or_changed;
1803 if (c_check_mbox_size)
1805 new_or_changed = (st.st_size > m->
size);
1819 if (!c_mail_check_recent ||
1825 else if (c_check_mbox_size)
1828 m->
size = (off_t) st.st_size;
1831 if (m->
newly_created && ((st.st_ctime != st.st_mtime) || (st.st_ctime != st.st_atime)))
1838 &
adata->stats_last_checked) > 0)
1874 .msg_save_hcache = NULL,
1876 .tags_commit = NULL,
1906 .msg_save_hcache = NULL,
1908 .tags_commit = NULL,
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration 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.
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Convenience wrapper for the config headers.
char * HomeDir
User's home directory.
int mutt_copy_message(FILE *fp_out, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Copy a message from a Mailbox.
Duplicate the structure of an entire email.
#define MUTT_CM_UPDATE
Update structs on sync.
#define CH_UPDATE
Update the status and x-status fields?
#define CH_FROM
Retain the "From " message separator?
#define CH_UPDATE_LEN
Update Lines: and Content-Length:
Convenience wrapper for the core headers.
int mutt_date_local_tz(time_t t)
Calculate the local timezone in seconds east of UTC.
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
void mutt_body_free(struct Body **ptr)
Free a Body.
bool email_cmp_strict(const struct Email *e1, const struct Email *e2)
Strictly compare message emails.
struct Email * email_new(void)
Create a new Email.
void email_free(struct Email **ptr)
Free an Email.
Structs that make up an email.
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
void mutt_file_get_stat_timespec(struct timespec *dest, struct stat *st, enum MuttStatType type)
Read the stat() time into a time value.
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
int mutt_file_stat_compare(struct stat *st1, enum MuttStatType st1_type, struct stat *st2, enum MuttStatType st2_type)
Compare two stat infos.
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
void mutt_file_touch_atime(int fd)
Set the access time to current time.
int mutt_file_check_empty(const char *path)
Is the mailbox empty.
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
int mutt_file_lock(int fd, bool excl, bool timeout)
(Try to) Lock a file using fcntl()
int mutt_file_timespec_compare(struct timespec *a, struct timespec *b)
Compare to time values.
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
int mutt_file_stat_timespec_compare(struct stat *st, enum MuttStatType type, struct timespec *b)
Compare stat info with a time value.
@ MUTT_STAT_CTIME
File/dir's ctime - creation time.
@ MUTT_STAT_ATIME
File/dir's atime - last accessed time.
@ MUTT_STAT_MTIME
File/dir's mtime - last modified time.
bool is_from(const char *s, char *path, size_t pathlen, time_t *tp)
Is a string a 'From' header line?
char * ShortHostname
Short version of the hostname.
char * Username
User's login name.
SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
#define mutt_message(...)
#define mutt_debug(LEVEL,...)
static bool mbox_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Implements MxOps::ac_add() -.
static bool mbox_ac_owns_path(struct Account *a, const char *path)
Check whether an Account owns a Mailbox path - Implements MxOps::ac_owns_path() -.
struct MxOps MxMmdfOps
MMDF Mailbox - Implements MxOps -.
struct MxOps MxMboxOps
Mbox Mailbox - Implements MxOps -.
static enum MxStatus mbox_mbox_check_stats(struct Mailbox *m, uint8_t flags)
Check the Mailbox statistics - Implements MxOps::mbox_check_stats() -.
static enum MxStatus mbox_mbox_check(struct Mailbox *m)
Check for new mail - Implements MxOps::mbox_check() -.
static enum MxStatus mbox_mbox_close(struct Mailbox *m)
Close a Mailbox - Implements MxOps::mbox_close() -.
static bool mbox_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a Mailbox for appending - Implements MxOps::mbox_open_append() -.
static enum MxOpenReturns mbox_mbox_open(struct Mailbox *m)
Open a Mailbox - Implements MxOps::mbox_open() -.
static enum MxStatus mbox_mbox_sync(struct Mailbox *m)
Save changes to the Mailbox - Implements MxOps::mbox_sync() -.
static int mbox_msg_close(struct Mailbox *m, struct Message *msg)
Close an email - Implements MxOps::msg_close() -.
static int mbox_msg_commit(struct Mailbox *m, struct Message *msg)
Save changes to an email - Implements MxOps::msg_commit() -.
static int mmdf_msg_commit(struct Mailbox *m, struct Message *msg)
Save changes to an email - Implements MxOps::msg_commit() -.
static bool mbox_msg_open_new(struct Mailbox *m, struct Message *msg, const struct Email *e)
Open a new message in a Mailbox - Implements MxOps::msg_open_new() -.
static bool mbox_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
Open an email message in a Mailbox - Implements MxOps::msg_open() -.
static int mbox_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Implements MxOps::msg_padding_size() -.
static int mmdf_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Implements MxOps::msg_padding_size() -.
static int mbox_path_canon(char *buf, size_t buflen)
Canonicalise a Mailbox path - Implements MxOps::path_canon() -.
static int mbox_path_is_empty(const char *path)
Is the mailbox empty - Implements MxOps::path_is_empty() -.
static int mbox_path_parent(char *buf, size_t buflen)
Find the parent of a Mailbox path - Implements MxOps::path_parent() -.
static int mbox_path_pretty(char *buf, size_t buflen, const char *folder)
Abbreviate a Mailbox path - Implements MxOps::path_pretty() -.
enum MailboxType mbox_path_probe(const char *path, const struct stat *st)
Is this an mbox Mailbox? - Implements MxOps::path_probe() -.
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
@ LL_DEBUG1
Log at debug level 1.
void mailbox_update(struct Mailbox *m)
Get the mailbox's current size.
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
@ NT_MAILBOX_RESORT
Email list needs resorting.
@ NT_MAILBOX_INVALID
Email list was changed.
@ NT_MAILBOX_UPDATE
Update internal tables.
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
MailboxType
Supported mailbox formats.
@ MUTT_MMDF
'mmdf' Mailbox type
@ MUTT_MBOX
'mbox' Mailbox type
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
static enum MxOpenReturns mbox_parse_mailbox(struct Mailbox *m)
Read a mailbox from disk.
static struct MboxAccountData * mbox_adata_new(void)
Create a new MboxAccountData struct.
static bool mbox_has_new(struct Mailbox *m)
Does the mailbox have new mail.
static int mbox_lock_mailbox(struct Mailbox *m, bool excl, bool retry)
Lock a mailbox.
static struct MboxAccountData * mbox_adata_get(struct Mailbox *m)
Get the private data associated with a Mailbox.
static int init_mailbox(struct Mailbox *m)
Add Mbox data to the Mailbox.
static FILE * mbox_open_readwrite(struct Mailbox *m)
Open an mbox read-write.
static bool test_last_status_new(FILE *fp)
Is the last message new.
static int fseek_last_message(FILE *fp)
Find the last message in the file.
static FILE * mbox_open_readonly(struct Mailbox *m)
Open an mbox read-only.
static void mbox_unlock_mailbox(struct Mailbox *m)
Unlock a mailbox.
bool mbox_test_new_folder(const char *path)
Test if an mbox or mmdf mailbox has new mail.
static enum MxOpenReturns mmdf_parse_mailbox(struct Mailbox *m)
Read a mailbox in MMDF format.
void mbox_reset_atime(struct Mailbox *m, struct stat *st)
Reset the access time on the mailbox file.
static void mbox_adata_free(void **ptr)
Free the private Account data - Implements Account::adata_free()
static int reopen_mailbox(struct Mailbox *m)
Close and reopen a mailbox.
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Convenience wrapper for the library headers.
bool mutt_path_abbr_folder(char *buf, const char *folder)
Create a folder abbreviation.
bool mutt_path_pretty(char *buf, size_t buflen, const char *homedir, bool is_dir)
Tidy a filesystem path.
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final '/'.
bool mutt_path_canon(char *buf, size_t buflen, const char *homedir, bool is_dir)
Create the canonical version of a path.
bool mutt_path_parent(char *buf)
Find the parent of a path.
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Many unsorted constants and some structs.
@ MUTT_READ
Messages that have been read.
@ MUTT_PURGE
Messages to be purged (bypass trash)
@ MUTT_TAG
Tagged messages.
@ MUTT_FLAG
Flagged messages.
@ MUTT_DELETE
Messages to be deleted.
@ MUTT_REPLIED
Messages that have been replied to.
Create/manipulate threading in emails.
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Some miscellaneous functions.
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
void mx_fastclose_mailbox(struct Mailbox *m, bool keep_account)
Free up memory associated with the Mailbox.
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
Return a stream pointer for a message.
void mx_alloc_memory(struct Mailbox *m)
Create storage for the emails.
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
#define MUTT_NEWFOLDER
Create a new folder - same as MUTT_APPEND, but uses mutt_file_fopen() with mode "w" for mbox-style fo...
#define MUTT_QUIET
Do not print any messages.
MxOpenReturns
Return values for mbox_open()
@ MX_OPEN_ERROR
Open failed with an error.
@ MX_OPEN_ABORT
Open was aborted.
@ MX_OPEN_OK
Open succeeded.
#define MUTT_PEEK
Revert atime back after taking a look (if applicable)
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
#define MUTT_MAILBOX_CHECK_FORCE_STATS
Ignore MailboxType and calculate statistics.
#define MUTT_MAILBOX_CHECK_FORCE
Ignore MailboxTime and check for new mail.
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_snc(), and mbox_close()
@ MX_STATUS_LOCKED
Couldn't lock the Mailbox.
@ MX_STATUS_ERROR
An error occurred.
@ MX_STATUS_OK
No changes.
@ MX_STATUS_REOPENED
Mailbox was reopened.
@ MX_STATUS_NEW_MAIL
New mail received in Mailbox.
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
Parses an RFC822 header.
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
@ MUTT_PROGRESS_READ
Progress tracks elements, according to $read_inc
@ MUTT_PROGRESS_WRITE
Progress tracks elements, according to $write_inc
void progress_free(struct Progress **ptr)
Free a Progress Bar.
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Prototypes for many functions.
#define mutt_set_flag(m, e, flag, bf)
#define STAILQ_FIRST(head)
#define TAILQ_EMPTY(head)
void mutt_sig_block(void)
Block signals during critical operations.
void mutt_sig_unblock(void)
Restore previously blocked signals.
@ SORT_ORDER
Sort by the order the messages appear in the mailbox.
A group of associated Mailboxes.
enum MailboxType type
Type of Mailboxes this Account contains.
void(* adata_free)(void **ptr)
Free the private data attached to the Account.
void * adata
Private data (for Mailbox backends)
struct MailboxList mailboxes
List of Mailboxes.
struct Body * parts
parts of a multipart or message/rfc822
LOFF_T offset
offset where the actual data begins
LOFF_T length
length (in bytes) of attachment
long hdr_offset
Offset in stream where the headers begin.
String manipulation buffer.
The envelope/body of an email.
bool purge
Skip trash folder when deleting.
struct Envelope * env
Envelope information.
int lines
How many lines in the body of this message?
struct Body * body
List of MIME parts.
bool old
Email is seen, but unread.
bool changed
Email has been edited.
LOFF_T offset
Where in the stream does this message begin?
bool attach_del
Has an attachment marked for deletion.
bool flagged
Marked important?
bool replied
Email has been replied to.
int msgno
Number displayed to the user.
bool deleted
Email is deleted.
int index
The absolute (unsorted) message number.
bool tagged
Email is tagged.
time_t received
Time when the message was placed in the mailbox.
struct AddressList return_path
Return path for the Email.
struct AddressList from
Email's 'From' list.
Store of new offsets, used by mutt_sync_mailbox()
struct Mailbox * mailbox
Mailbox in the list.
int vcount
The number of virtual messages.
bool changed
Mailbox has been modified.
bool has_new
Mailbox has new mail.
struct timespec mtime
Time Mailbox was last changed.
int * v2r
Mapping from virtual to real msgno.
int msg_new
Number of new messages.
int msg_count
Total number of messages.
int email_max
Number of pointers in emails.
enum MailboxType type
Mailbox type.
bool newly_created
Mbox or mmdf just popped into existence.
struct HashTable * subj_hash
Hash Table by subject.
struct Email ** emails
Array of Emails.
struct HashTable * id_hash
Hash Table by msg id.
struct Buffer pathbuf
Path of the Mailbox.
bool peekonly
Just taking a glance, revert atime.
int msg_deleted
Number of deleted messages.
struct Account * account
Account that owns this Mailbox.
off_t size
Size of the Mailbox.
struct HashTable * label_hash
Hash Table for x-labels.
int msg_flagged
Number of flagged messages.
struct timespec last_visited
Time of last exit from this mailbox.
bool readonly
Don't allow changes to the mailbox.
int msg_tagged
How many messages are tagged?
bool verbose
Display status messages?
int msg_unread
Number of unread messages.
Mbox-specific Account data -.
bool locked
is the mailbox locked?
struct timespec atime
File's last-access time.
A local copy of an email.
FILE * fp
pointer to the message data
bool write
nonzero if message is open for writing
enum MailboxType type
Mailbox type, e.g. MUTT_IMAP.
Container for Accounts, Notifications.
struct ConfigSubset * sub
Inherited config items.
Time value with nanosecond precision.
time_t tv_sec
Number of seconds since the epoch.
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
#define mutt_buffer_mktemp(buf)