NeoMutt  2022-04-29-178-g3b62e6
Teaching an old dog new tricks
DOXYGEN
mbox_check()

Check for new mail. More...

+ Collaboration diagram for mbox_check():

Functions

static enum MxStatus comp_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
static enum MxStatus imap_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
enum MxStatus maildir_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
enum MxStatus mh_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
static enum MxStatus mbox_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
static enum MxStatus nntp_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
static enum MxStatus nm_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
static enum MxStatus pop_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 

Detailed Description

Check for new mail.

Parameters
mMailbox
Return values
enumMxStatus

Contract

Function Documentation

◆ comp_mbox_check()

static enum MxStatus comp_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check() -.

Parameters
mMailbox
Return values
enumMxStatus

If the compressed file changes in size but the mailbox hasn't been changed in NeoMutt, then we can close and reopen the mailbox.

If the mailbox has been changed in NeoMutt, warn the user.

Definition at line 582 of file compress.c.

583{
584 if (!m->compress_info)
585 return MX_STATUS_ERROR;
586
587 struct CompressInfo *ci = m->compress_info;
588
589 const struct MxOps *ops = ci->child_ops;
590 if (!ops)
591 return MX_STATUS_ERROR;
592
593 int size = mutt_file_get_size(m->realpath);
594 if (size == ci->size)
595 return MX_STATUS_OK;
596
597 if (!lock_realpath(m, false))
598 {
599 mutt_error(_("Unable to lock mailbox"));
600 return MX_STATUS_ERROR;
601 }
602
603 int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
604 store_size(m);
606 if (rc == 0)
607 return MX_STATUS_ERROR;
608
609 return ops->mbox_check(m);
610}
static int execute_command(struct Mailbox *m, const char *command, const char *progress)
Run a system command.
Definition: compress.c:322
static void store_size(const struct Mailbox *m)
Save the size of the compressed file.
Definition: compress.c:179
static bool lock_realpath(struct Mailbox *m, bool excl)
Try to lock the Mailbox.realpath.
Definition: compress.c:86
static void unlock_realpath(struct Mailbox *m)
Unlock the mailbox->realpath.
Definition: compress.c:125
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1551
#define mutt_error(...)
Definition: logging.h:87
#define _(a)
Definition: message.h:28
@ MX_STATUS_ERROR
An error occurred.
Definition: mxapi.h:85
@ MX_STATUS_OK
No changes.
Definition: mxapi.h:86
Private data for compress.
Definition: lib.h:47
const char * cmd_open
open-hook command
Definition: lib.h:50
const struct MxOps * child_ops
callbacks of de-compressed file
Definition: lib.h:52
long size
size of the compressed file
Definition: lib.h:51
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:81
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:121
Definition: mxapi.h:112
enum MxStatus(* mbox_check)(struct Mailbox *m)
Definition: mxapi.h:188
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_mbox_check()

static enum MxStatus imap_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check() -.

Parameters
mMailbox
Return values
>0Success, e.g. MX_STATUS_REOPENED
-1Failure

Definition at line 2167 of file imap.c.

2168{
2170 enum MxStatus rc = imap_check_mailbox(m, false);
2171 /* NOTE - mv might have been changed at this point. In particular,
2172 * m could be NULL. Beware. */
2174
2175 return rc;
2176}
void imap_allow_reopen(struct Mailbox *m)
Allow re-opening a folder upon expunge.
Definition: util.c:1016
void imap_disallow_reopen(struct Mailbox *m)
Disallow re-opening a folder upon expunge.
Definition: util.c:1029
enum MxStatus imap_check_mailbox(struct Mailbox *m, bool force)
Use the NOOP or IDLE command to poll for new mail.
Definition: imap.c:1106
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_snc(), and mbox_close()
Definition: mxapi.h:84
+ Here is the call graph for this function:

◆ maildir_mbox_check()

enum MxStatus maildir_mbox_check ( struct Mailbox m)

Check for new mail - Implements MxOps::mbox_check() -.

This function handles arrival of new mail and reopening of maildir folders. The basic idea here is we check to see if either the new or cur subdirectories have changed, and if so, we scan them for the list of files. We check for newly added messages, and then merge the flags messages we already knew about. We don't treat either subdirectory differently, as mail could be copied directly into the cur directory from another agent.

Definition at line 1168 of file maildir.c.

1169{
1170 struct stat st_new = { 0 }; /* status of the "new" subdirectory */
1171 struct stat st_cur = { 0 }; /* status of the "cur" subdirectory */
1172 int changed = MMC_NO_DIRS; /* which subdirectories have changed */
1173 bool occult = false; /* messages were removed from the mailbox */
1174 int num_new = 0; /* number of new messages added to the mailbox */
1175 bool flags_changed = false; /* message flags were changed in the mailbox */
1176 struct HashTable *fnames = NULL; /* hash table for quickly looking up the base filename
1177 for a maildir message */
1179
1180 /* XXX seems like this check belongs in mx_mbox_check() rather than here. */
1181 const bool c_check_new = cs_subset_bool(NeoMutt->sub, "check_new");
1182 if (!c_check_new)
1183 return MX_STATUS_OK;
1184
1185 struct Buffer *buf = mutt_buffer_pool_get();
1186 mutt_buffer_printf(buf, "%s/new", mailbox_path(m));
1187 if (stat(mutt_buffer_string(buf), &st_new) == -1)
1188 {
1190 return MX_STATUS_ERROR;
1191 }
1192
1193 mutt_buffer_printf(buf, "%s/cur", mailbox_path(m));
1194 if (stat(mutt_buffer_string(buf), &st_cur) == -1)
1195 {
1197 return MX_STATUS_ERROR;
1198 }
1199
1200 /* determine which subdirectories need to be scanned */
1202 changed = MMC_NEW_DIR;
1204 changed |= MMC_CUR_DIR;
1205
1206 if (changed == MMC_NO_DIRS)
1207 {
1209 return MX_STATUS_OK; /* nothing to do */
1210 }
1211
1212 /* Update the modification times on the mailbox.
1213 *
1214 * The monitor code notices changes in the open mailbox too quickly.
1215 * In practice, this sometimes leads to all the new messages not being
1216 * noticed during the SAME group of mtime stat updates. To work around
1217 * the problem, don't update the stat times for a monitor caused check. */
1218#ifdef USE_INOTIFY
1220 MonitorContextChanged = false;
1221 else
1222#endif
1223 {
1226 }
1227
1228 /* do a fast scan of just the filenames in
1229 * the subdirectories that have changed. */
1230 struct MdEmailArray mda = ARRAY_HEAD_INITIALIZER;
1231 if (changed & MMC_NEW_DIR)
1232 maildir_parse_dir(m, &mda, "new", NULL);
1233 if (changed & MMC_CUR_DIR)
1234 maildir_parse_dir(m, &mda, "cur", NULL);
1235
1236 /* we create a hash table keyed off the canonical (sans flags) filename
1237 * of each message we scanned. This is used in the loop over the
1238 * existing messages below to do some correlation. */
1240
1241 struct MdEmail *md = NULL;
1242 struct MdEmail **mdp = NULL;
1243 ARRAY_FOREACH(mdp, &mda)
1244 {
1245 md = *mdp;
1248 mutt_hash_insert(fnames, md->canon_fname, md);
1249 }
1250
1251 /* check for modifications and adjust flags */
1252 for (int i = 0; i < m->msg_count; i++)
1253 {
1254 struct Email *e = m->emails[i];
1255 if (!e)
1256 break;
1257
1258 e->active = false;
1260 md = mutt_hash_find(fnames, mutt_buffer_string(buf));
1261 if (md && md->email)
1262 {
1263 /* message already exists, merge flags */
1264 e->active = true;
1265
1266 /* check to see if the message has moved to a different
1267 * subdirectory. If so, update the associated filename. */
1268 if (!mutt_str_equal(e->path, md->email->path))
1269 mutt_str_replace(&e->path, md->email->path);
1270
1271 /* if the user hasn't modified the flags on this message, update
1272 * the flags we just detected. */
1273 if (!e->changed)
1274 if (maildir_update_flags(m, e, md->email))
1275 flags_changed = true;
1276
1277 if (e->deleted == e->trash)
1278 {
1279 if (e->deleted != md->email->deleted)
1280 {
1281 e->deleted = md->email->deleted;
1282 flags_changed = true;
1283 }
1284 }
1285 e->trash = md->email->trash;
1286
1287 /* this is a duplicate of an existing email, so remove it */
1288 email_free(&md->email);
1289 }
1290 /* This message was not in the list of messages we just scanned.
1291 * Check to see if we have enough information to know if the
1292 * message has disappeared out from underneath us. */
1293 else if (((changed & MMC_NEW_DIR) && mutt_strn_equal(e->path, "new/", 4)) ||
1294 ((changed & MMC_CUR_DIR) && mutt_strn_equal(e->path, "cur/", 4)))
1295 {
1296 /* This message disappeared, so we need to simulate a "reopen"
1297 * event. We know it disappeared because we just scanned the
1298 * subdirectory it used to reside in. */
1299 occult = true;
1300 e->deleted = true;
1301 e->purge = true;
1302 }
1303 else
1304 {
1305 /* This message resides in a subdirectory which was not
1306 * modified, so we assume that it is still present and
1307 * unchanged. */
1308 e->active = true;
1309 }
1310 }
1311
1312 /* destroy the file name hash */
1313 mutt_hash_free(&fnames);
1314
1315 /* If we didn't just get new mail, update the tables. */
1316 if (occult)
1318
1319 /* do any delayed parsing we need to do. */
1320 maildir_delayed_parsing(m, &mda, NULL);
1321
1322 /* Incorporate new messages */
1323 num_new = maildir_move_to_mailbox(m, &mda);
1324 if (num_new > 0)
1325 {
1327 m->changed = true;
1328 }
1329
1331
1332 ARRAY_FREE(&mda);
1333 if (occult)
1334 return MX_STATUS_REOPENED;
1335 if (num_new > 0)
1336 return MX_STATUS_NEW_MAIL;
1337 if (flags_changed)
1338 return MX_STATUS_FLAGS;
1339 return MX_STATUS_OK;
1340}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:211
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:86
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:203
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition: array.h:57
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:158
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:430
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
void mutt_file_get_stat_timespec(struct timespec *dest, struct stat *st, enum MuttStatType type)
Read the stat() time into a time value.
Definition: file.c:1611
int mutt_file_stat_timespec_compare(struct stat *st, enum MuttStatType type, struct timespec *b)
Compare stat info with a time value.
Definition: file.c:1651
@ MUTT_STAT_MTIME
File/dir's mtime - last modified time.
Definition: file.h:63
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys)
Definition: hash.c:335
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:362
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:259
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:457
#define MUTT_HASH_NO_FLAGS
No flags are set.
Definition: hash.h:109
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:222
@ NT_MAILBOX_RESORT
Email list needs resorting.
Definition: mailbox.h:178
@ NT_MAILBOX_INVALID
Email list was changed.
Definition: mailbox.h:177
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:211
bool maildir_update_flags(struct Mailbox *m, struct Email *e_old, struct Email *e_new)
Update the mailbox flags.
Definition: shared.c:122
struct MaildirMboxData * maildir_mdata_get(struct Mailbox *m)
Get the private data for this Mailbox.
Definition: mdata.c:58
int maildir_move_to_mailbox(struct Mailbox *m, struct MdEmailArray *mda)
Copy the Maildir list to the Mailbox.
Definition: shared.c:75
int maildir_parse_dir(struct Mailbox *m, struct MdEmailArray *mda, const char *subdir, struct Progress *progress)
Read a Maildir mailbox.
Definition: maildir.c:513
#define MMC_CUR_DIR
'cur' directory changed
Definition: maildir.c:75
#define MMC_NO_DIRS
No directories changed.
Definition: maildir.c:73
#define MMC_NEW_DIR
'new' directory changed
Definition: maildir.c:74
void maildir_delayed_parsing(struct Mailbox *m, struct MdEmailArray *mda, struct Progress *progress)
This function does the second parsing pass.
Definition: maildir.c:597
void maildir_canon_filename(struct Buffer *dest, const char *src)
Generate the canonical filename for a Maildir folder.
Definition: maildir.c:725
bool MonitorContextChanged
true after the current mailbox has changed
Definition: monitor.c:51
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:784
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:473
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
@ MX_STATUS_FLAGS
Nondestructive flags change (IMAP)
Definition: mxapi.h:90
@ MX_STATUS_REOPENED
Mailbox was reopened.
Definition: mxapi.h:89
@ MX_STATUS_NEW_MAIL
New mail received in Mailbox.
Definition: mxapi.h:87
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
String manipulation buffer.
Definition: buffer.h:34
The envelope/body of an email.
Definition: email.h:37
bool purge
Skip trash folder when deleting.
Definition: email.h:77
bool active
Message is not to be removed.
Definition: email.h:74
bool changed
Email has been edited.
Definition: email.h:75
char * path
Path of Email (for local Mailboxes)
Definition: email.h:68
bool deleted
Email is deleted.
Definition: email.h:76
bool trash
Message is marked as trashed on disk (used by the maildir_trash option)
Definition: email.h:51
A Hash Table.
Definition: hash.h:97
bool changed
Mailbox has been modified.
Definition: mailbox.h:111
struct timespec mtime
Time Mailbox was last changed.
Definition: mailbox.h:104
int msg_count
Total number of messages.
Definition: mailbox.h:88
void * mdata
Driver specific data.
Definition: mailbox.h:133
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
Maildir-specific Mailbox data -.
Definition: mdata.h:35
struct timespec mtime_cur
Timestamp of the 'cur' dir.
Definition: mdata.h:36
A Maildir Email helper.
Definition: mdemail.h:34
char * canon_fname
Definition: mdemail.h:36
struct Email * email
Definition: mdemail.h:35
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mh_mbox_check()

enum MxStatus mh_mbox_check ( struct Mailbox m)

Check for new mail - Implements MxOps::mbox_check() -.

This function handles arrival of new mail and reopening of mh/maildir folders. Things are getting rather complex because we don't have a well-defined "mailbox order", so the tricks from mbox.c and mx.c won't work here.

Don't change this code unless you really understand what happens.

Definition at line 892 of file mh.c.

893{
894 char buf[PATH_MAX] = { 0 };
895 struct stat st = { 0 };
896 struct stat st_cur = { 0 };
897 bool modified = false, occult = false, flags_changed = false;
898 int num_new = 0;
899 struct MhSequences mhs = { 0 };
900 struct HashTable *fnames = NULL;
902
903 const bool c_check_new = cs_subset_bool(NeoMutt->sub, "check_new");
904 if (!c_check_new)
905 return MX_STATUS_OK;
906
907 mutt_str_copy(buf, mailbox_path(m), sizeof(buf));
908 if (stat(buf, &st) == -1)
909 return MX_STATUS_ERROR;
910
911 /* create .mh_sequences when there isn't one. */
912 snprintf(buf, sizeof(buf), "%s/.mh_sequences", mailbox_path(m));
913 int rc = stat(buf, &st_cur);
914 if ((rc == -1) && (errno == ENOENT))
915 {
916 char *tmp = NULL;
917 FILE *fp = NULL;
918
919 if (mh_mkstemp(m, &fp, &tmp))
920 {
921 mutt_file_fclose(&fp);
922 if (mutt_file_safe_rename(tmp, buf) == -1)
923 unlink(tmp);
924 FREE(&tmp);
925 }
926 }
927
928 if ((rc == -1) && (stat(buf, &st_cur) == -1))
929 modified = true;
930
932 (mutt_file_stat_timespec_compare(&st_cur, MUTT_STAT_MTIME, &mdata->mtime_cur) > 0))
933 {
934 modified = true;
935 }
936
937 if (!modified)
938 return MX_STATUS_OK;
939
940 /* Update the modification times on the mailbox.
941 *
942 * The monitor code notices changes in the open mailbox too quickly.
943 * In practice, this sometimes leads to all the new messages not being
944 * noticed during the SAME group of mtime stat updates. To work around
945 * the problem, don't update the stat times for a monitor caused check. */
946#ifdef USE_INOTIFY
948 MonitorContextChanged = false;
949 else
950#endif
951 {
954 }
955
956 struct MdEmailArray mda = ARRAY_HEAD_INITIALIZER;
957
958 mh_parse_dir(m, &mda, NULL);
959 mh_delayed_parsing(m, &mda, NULL);
960
961 if (mh_seq_read(&mhs, mailbox_path(m)) < 0)
962 return MX_STATUS_ERROR;
963 mh_update_maildir(&mda, &mhs);
964 mh_seq_free(&mhs);
965
966 /* check for modifications and adjust flags */
968
969 struct MdEmail *md = NULL;
970 struct MdEmail **mdp = NULL;
971 ARRAY_FOREACH(mdp, &mda)
972 {
973 md = *mdp;
974 /* the hash key must survive past the header, which is freed below. */
976 mutt_hash_insert(fnames, md->canon_fname, md);
977 }
978
979 for (int i = 0; i < m->msg_count; i++)
980 {
981 struct Email *e = m->emails[i];
982 if (!e)
983 break;
984
985 e->active = false;
986
987 md = mutt_hash_find(fnames, e->path);
988 if (md && md->email && email_cmp_strict(e, md->email))
989 {
990 e->active = true;
991 /* found the right message */
992 if (!e->changed)
993 if (maildir_update_flags(m, e, md->email))
994 flags_changed = true;
995
996 email_free(&md->email);
997 }
998 else /* message has disappeared */
999 occult = true;
1000 }
1001
1002 /* destroy the file name hash */
1003
1004 mutt_hash_free(&fnames);
1005
1006 /* If we didn't just get new mail, update the tables. */
1007 if (occult)
1009
1010 /* Incorporate new messages */
1011 num_new = maildir_move_to_mailbox(m, &mda);
1012 if (num_new > 0)
1013 {
1015 m->changed = true;
1016 }
1017
1018 ARRAY_FREE(&mda);
1019 if (occult)
1020 return MX_STATUS_REOPENED;
1021 if (num_new > 0)
1022 return MX_STATUS_NEW_MAIL;
1023 if (flags_changed)
1024 return MX_STATUS_FLAGS;
1025 return MX_STATUS_OK;
1026}
bool email_cmp_strict(const struct Email *e1, const struct Email *e2)
Strictly compare message emails.
Definition: email.c:100
int mutt_file_safe_rename(const char *src, const char *target)
NFS-safe renaming of files.
Definition: file.c:344
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
#define FREE(x)
Definition: memory.h:43
void mh_delayed_parsing(struct Mailbox *m, struct MdEmailArray *mda, struct Progress *progress)
This function does the second parsing pass.
Definition: mh.c:614
void mh_update_maildir(struct MdEmailArray *mda, struct MhSequences *mhs)
Update our record of flags.
Definition: mh.c:260
bool mh_mkstemp(struct Mailbox *m, FILE **fp, char **tgt)
Create a temporary file.
Definition: mh.c:78
int mh_parse_dir(struct Mailbox *m, struct MdEmailArray *mda, struct Progress *progress)
Read a Maildir mailbox.
Definition: mh.c:502
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:629
#define PATH_MAX
Definition: mutt.h:40
void mh_seq_free(struct MhSequences *mhs)
Free some sequences.
Definition: sequence.c:67
int mh_seq_read(struct MhSequences *mhs, const char *path)
Read a set of MH sequences.
Definition: sequence.c:375
Set of MH sequence numbers.
Definition: sequence.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mbox_mbox_check()

static enum MxStatus mbox_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check() -.

Parameters
[in]mMailbox
Return values
MX_STATUS_REOPENEDMailbox has been reopened
MX_STATUS_NEW_MAILNew mail has arrived
MX_STATUS_LOCKEDCouldn't lock the file

Definition at line 1031 of file mbox.c.

1032{
1034 if (!adata)
1035 return MX_STATUS_ERROR;
1036
1037 if (!adata->fp)
1038 {
1039 if (mbox_mbox_open(m) != MX_OPEN_OK)
1040 return MX_STATUS_ERROR;
1042 }
1043 if (!adata->fp)
1044 return MX_STATUS_ERROR;
1045
1046 struct stat st = { 0 };
1047 bool unlock = false;
1048 bool modified = false;
1049
1050 if (stat(mailbox_path(m), &st) == 0)
1051 {
1053 (st.st_size == m->size))
1054 {
1055 return MX_STATUS_OK;
1056 }
1057
1058 if (st.st_size == m->size)
1059 {
1060 /* the file was touched, but it is still the same length, so just exit */
1062 return MX_STATUS_OK;
1063 }
1064
1065 if (st.st_size > m->size)
1066 {
1067 /* lock the file if it isn't already */
1068 if (!adata->locked)
1069 {
1071 if (mbox_lock_mailbox(m, false, false) == -1)
1072 {
1074 /* we couldn't lock the mailbox, but nothing serious happened:
1075 * probably the new mail arrived: no reason to wait till we can
1076 * parse it: we'll get it on the next pass */
1077 return MX_STATUS_LOCKED;
1078 }
1079 unlock = 1;
1080 }
1081
1082 /* Check to make sure that the only change to the mailbox is that
1083 * message(s) were appended to this file. My heuristic is that we should
1084 * see the message separator at *exactly* what used to be the end of the
1085 * folder. */
1086 char buf[1024] = { 0 };
1087 if (!mutt_file_seek(adata->fp, m->size, SEEK_SET))
1088 {
1089 goto error;
1090 }
1091 if (fgets(buf, sizeof(buf), adata->fp))
1092 {
1093 if (((m->type == MUTT_MBOX) && mutt_str_startswith(buf, "From ")) ||
1094 ((m->type == MUTT_MMDF) && mutt_str_equal(buf, MMDF_SEP)))
1095 {
1096 if (!mutt_file_seek(adata->fp, m->size, SEEK_SET))
1097 {
1098 goto error;
1099 }
1100
1101 int old_msg_count = m->msg_count;
1102 if (m->type == MUTT_MBOX)
1104 else
1106
1107 if (m->msg_count > old_msg_count)
1109
1110 /* Only unlock the folder if it was locked inside of this routine.
1111 * It may have been locked elsewhere, like in
1112 * mutt_checkpoint_mailbox(). */
1113 if (unlock)
1114 {
1117 }
1118
1119 return MX_STATUS_NEW_MAIL; /* signal that new mail arrived */
1120 }
1121 else
1122 modified = true;
1123 }
1124 else
1125 {
1126 mutt_debug(LL_DEBUG1, "fgets returned NULL\n");
1127 modified = true;
1128 }
1129 }
1130 else
1131 modified = true;
1132 }
1133
1134 if (modified)
1135 {
1136 if (reopen_mailbox(m) != -1)
1137 {
1139 if (unlock)
1140 {
1143 }
1144 return MX_STATUS_REOPENED;
1145 }
1146 }
1147
1148 /* fatal error */
1149
1150error:
1152 mx_fastclose_mailbox(m, false);
1154 mutt_error(_("Mailbox was corrupted"));
1155 return MX_STATUS_ERROR;
1156}
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:690
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
static enum MxOpenReturns mbox_mbox_open(struct Mailbox *m)
Open a Mailbox - Implements MxOps::mbox_open() -.
Definition: mbox.c:930
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:46
@ MUTT_MBOX
'mbox' Mailbox type
Definition: mailbox.h:45
#define MMDF_SEP
Definition: lib.h:60
static enum MxOpenReturns mbox_parse_mailbox(struct Mailbox *m)
Read a mailbox from disk.
Definition: mbox.c:348
static int mbox_lock_mailbox(struct Mailbox *m, bool excl, bool retry)
Lock a mailbox.
Definition: mbox.c:139
static struct MboxAccountData * mbox_adata_get(struct Mailbox *m)
Get the private data associated with a Mailbox.
Definition: mbox.c:99
static void mbox_unlock_mailbox(struct Mailbox *m)
Unlock a mailbox.
Definition: mbox.c:161
static enum MxOpenReturns mmdf_parse_mailbox(struct Mailbox *m)
Read a mailbox in MMDF format.
Definition: mbox.c:181
static int reopen_mailbox(struct Mailbox *m)
Close and reopen a mailbox.
Definition: mbox.c:536
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:227
void mx_fastclose_mailbox(struct Mailbox *m, bool keep_account)
Free up memory associated with the Mailbox.
Definition: mx.c:430
@ MX_OPEN_OK
Open succeeded.
Definition: mxapi.h:98
@ MX_STATUS_LOCKED
Couldn't lock the Mailbox.
Definition: mxapi.h:88
void mutt_sig_block(void)
Block signals during critical operations.
Definition: signal.c:150
void mutt_sig_unblock(void)
Restore previously blocked signals.
Definition: signal.c:168
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
off_t size
Size of the Mailbox.
Definition: mailbox.h:84
Mbox-specific Account data -.
Definition: lib.h:49
FILE * fp
Mailbox file.
Definition: lib.h:50
bool locked
is the mailbox locked?
Definition: lib.h:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ nntp_mbox_check()

static enum MxStatus nntp_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check() -.

Parameters
mMailbox
Return values
enumMxStatus

Definition at line 2463 of file nntp.c.

2464{
2465 enum MxStatus rc = check_mailbox(m);
2466 if (rc == MX_STATUS_OK)
2467 {
2468 struct NntpMboxData *mdata = m->mdata;
2469 struct NntpAccountData *adata = mdata->adata;
2471 }
2472 return rc;
2473}
void nntp_newsrc_close(struct NntpAccountData *adata)
Unlock and close .newsrc file.
Definition: newsrc.c:118
static enum MxStatus check_mailbox(struct Mailbox *m)
Check current newsgroup for new articles.
Definition: nntp.c:1433
NNTP-specific Account data -.
Definition: adata.h:37
NNTP-specific Mailbox data -.
Definition: mdata.h:33
struct NntpAccountData * adata
Definition: mdata.h:47
+ Here is the call graph for this function:

◆ nm_mbox_check()

static enum MxStatus nm_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check() -.

Parameters
mMailbox
Return values
enumMxStatus

Definition at line 2067 of file notmuch.c.

2068{
2069 struct NmMboxData *mdata = nm_mdata_get(m);
2070 time_t mtime = 0;
2071 if (!mdata || (nm_db_get_mtime(m, &mtime) != 0))
2072 return MX_STATUS_ERROR;
2073
2074 int new_flags = 0;
2075 bool occult = false;
2076
2077 if (m->mtime.tv_sec >= mtime)
2078 {
2079 mutt_debug(LL_DEBUG2, "nm: check unnecessary (db=%lu mailbox=%lu)\n", mtime,
2080 m->mtime.tv_sec);
2081 return MX_STATUS_OK;
2082 }
2083
2084 mutt_debug(LL_DEBUG1, "nm: checking (db=%lu mailbox=%lu)\n", mtime, m->mtime.tv_sec);
2085
2086 notmuch_query_t *q = get_query(m, false);
2087 if (!q)
2088 goto done;
2089
2090 mutt_debug(LL_DEBUG1, "nm: start checking (count=%d)\n", m->msg_count);
2091 mdata->oldmsgcount = m->msg_count;
2092
2093 for (int i = 0; i < m->msg_count; i++)
2094 {
2095 struct Email *e = m->emails[i];
2096 if (!e)
2097 break;
2098
2099 e->active = false;
2100 }
2101
2102 int limit = get_limit(mdata);
2103
2104 notmuch_messages_t *msgs = get_messages(q);
2105
2106 // TODO: Analyze impact of removing this version guard.
2107#if LIBNOTMUCH_CHECK_VERSION(5, 0, 0)
2108 if (!msgs)
2109 return MX_STATUS_OK;
2110#elif LIBNOTMUCH_CHECK_VERSION(4, 3, 0)
2111 if (!msgs)
2112 goto done;
2113#endif
2114
2115 struct HeaderCache *h = nm_hcache_open(m);
2116
2117 for (int i = 0; notmuch_messages_valid(msgs) && ((limit == 0) || (i < limit));
2118 notmuch_messages_move_to_next(msgs), i++)
2119 {
2120 notmuch_message_t *msg = notmuch_messages_get(msgs);
2121 struct Email *e = get_mutt_email(m, msg);
2122
2123 if (!e)
2124 {
2125 /* new email */
2126 append_message(h, m, msg, false);
2127 notmuch_message_destroy(msg);
2128 continue;
2129 }
2130
2131 /* message already exists, merge flags */
2132 e->active = true;
2133
2134 /* Check to see if the message has moved to a different subdirectory.
2135 * If so, update the associated filename. */
2136 const char *new_file = get_message_last_filename(msg);
2137 char old_file[PATH_MAX] = { 0 };
2138 email_get_fullpath(e, old_file, sizeof(old_file));
2139
2140 if (!mutt_str_equal(old_file, new_file))
2141 update_message_path(e, new_file);
2142
2143 if (!e->changed)
2144 {
2145 /* if the user hasn't modified the flags on this message, update the
2146 * flags we just detected. */
2147 struct Email e_tmp = { 0 };
2148 e_tmp.edata = maildir_edata_new();
2149 maildir_parse_flags(&e_tmp, new_file);
2150 e_tmp.old = e->old;
2151 maildir_update_flags(m, e, &e_tmp);
2152 maildir_edata_free(&e_tmp.edata);
2153 }
2154
2155 if (update_email_tags(e, msg) == 0)
2156 new_flags++;
2157
2158 notmuch_message_destroy(msg);
2159 }
2160
2161 nm_hcache_close(h);
2162
2163 for (int i = 0; i < m->msg_count; i++)
2164 {
2165 struct Email *e = m->emails[i];
2166 if (!e)
2167 break;
2168
2169 if (!e->active)
2170 {
2171 occult = true;
2172 break;
2173 }
2174 }
2175
2176 if (m->msg_count > mdata->oldmsgcount)
2178done:
2179 if (q)
2180 notmuch_query_destroy(q);
2181
2182 nm_db_release(m);
2183
2185 m->mtime.tv_nsec = 0;
2186
2187 mutt_debug(LL_DEBUG1, "nm: ... check done [count=%d, new_flags=%d, occult=%d]\n",
2188 m->msg_count, new_flags, occult);
2189
2190 if (occult)
2191 return MX_STATUS_REOPENED;
2192 if (m->msg_count > mdata->oldmsgcount)
2193 return MX_STATUS_NEW_MAIL;
2194 if (new_flags)
2195 return MX_STATUS_FLAGS;
2196 return MX_STATUS_OK;
2197}
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:427
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
void maildir_edata_free(void **ptr)
Free the private Email data - Implements Email::edata_free()
Definition: edata.c:38
struct MaildirEmailData * maildir_edata_new(void)
Create a new MaildirEmailData object.
Definition: edata.c:53
void maildir_parse_flags(struct Email *e, const char *path)
Parse Maildir file flags.
Definition: maildir.c:809
int nm_db_get_mtime(struct Mailbox *m, time_t *mtime)
Get the database modification time.
Definition: db.c:275
int nm_db_release(struct Mailbox *m)
Close the Notmuch database.
Definition: db.c:193
struct NmMboxData * nm_mdata_get(struct Mailbox *m)
Get the Notmuch Mailbox data.
Definition: mdata.c:97
static char * email_get_fullpath(struct Email *e, char *buf, size_t buflen)
Get the full path of an email.
Definition: notmuch.c:224
static void nm_hcache_close(struct HeaderCache *h)
Close the header cache.
Definition: notmuch.c:123
static int get_limit(struct NmMboxData *mdata)
Get the database limit.
Definition: notmuch.c:396
static void append_message(struct HeaderCache *h, struct Mailbox *m, notmuch_message_t *msg, bool dedup)
Associate a message.
Definition: notmuch.c:733
static struct HeaderCache * nm_hcache_open(struct Mailbox *m)
Open a header cache.
Definition: notmuch.c:109
static notmuch_query_t * get_query(struct Mailbox *m, bool writable)
Create a new query.
Definition: notmuch.c:431
static int update_message_path(struct Email *e, const char *path)
Set the path for a message.
Definition: notmuch.c:514
static const char * get_message_last_filename(notmuch_message_t *msg)
Get a message's last filename.
Definition: notmuch.c:646
static int update_email_tags(struct Email *e, notmuch_message_t *msg)
Update the Email's tags from Notmuch.
Definition: notmuch.c:463
static notmuch_messages_t * get_messages(notmuch_query_t *query)
Load messages for a query.
Definition: notmuch.c:897
static struct Email * get_mutt_email(struct Mailbox *m, notmuch_message_t *msg)
Get the Email of a Notmuch message.
Definition: notmuch.c:699
void * edata
Driver-specific data.
Definition: email.h:72
bool old
Email is seen, but unread.
Definition: email.h:47
Header cache structure.
Definition: lib.h:87
Notmuch-specific Mailbox data -.
Definition: mdata.h:34
int oldmsgcount
Definition: mdata.h:41
long tv_nsec
Number of nanosecond, on top.
Definition: file.h:51
time_t tv_sec
Number of seconds since the epoch.
Definition: file.h:50
+ Here is the call graph for this function:

◆ pop_mbox_check()

static enum MxStatus pop_mbox_check ( struct Mailbox m)
static

Check for new mail - Implements MxOps::mbox_check() -.

Definition at line 819 of file pop.c.

820{
822
823 const short c_pop_check_interval = cs_subset_number(NeoMutt->sub, "pop_check_interval");
824 if ((adata->check_time + c_pop_check_interval) > mutt_date_epoch())
825 return MX_STATUS_OK;
826
827 pop_logout(m);
828
830
831 if (pop_open_connection(adata) < 0)
832 return MX_STATUS_ERROR;
833
834 m->size = adata->size;
835
836 mutt_message(_("Checking for new messages..."));
837
838 int old_msg_count = m->msg_count;
839 int rc = pop_fetch_headers(m);
841 if (m->msg_count > old_msg_count)
843
844 if (rc < 0)
845 return MX_STATUS_ERROR;
846
847 if (rc > 0)
848 return MX_STATUS_NEW_MAIL;
849
850 return MX_STATUS_OK;
851}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
#define mutt_message(...)
Definition: logging.h:86
struct PopAccountData * pop_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:64
int pop_open_connection(struct PopAccountData *adata)
Open connection and authenticate.
Definition: lib.c:308
void pop_logout(struct Mailbox *m)
Logout from a POP server.
Definition: lib.c:416
static void pop_clear_cache(struct PopAccountData *adata)
Delete all cached messages.
Definition: pop.c:491
static int pop_fetch_headers(struct Mailbox *m)
Read headers.
Definition: pop.c:321
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:97
POP-specific Account data -.
Definition: adata.h:37
+ Here is the call graph for this function: