NeoMutt  2023-03-22
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...
 
static enum MxStatus maildir_mbox_check (struct Mailbox *m)
 Check for new mail - Implements MxOps::mbox_check() -. More...
 
static 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
Precondition
m is not NULL

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 584 of file compress.c.

585{
586 if (!m->compress_info)
587 return MX_STATUS_ERROR;
588
589 struct CompressInfo *ci = m->compress_info;
590
591 const struct MxOps *ops = ci->child_ops;
592 if (!ops)
593 return MX_STATUS_ERROR;
594
595 int size = mutt_file_get_size(m->realpath);
596 if (size == ci->size)
597 return MX_STATUS_OK;
598
599 if (!lock_realpath(m, false))
600 {
601 mutt_error(_("Unable to lock mailbox"));
602 return MX_STATUS_ERROR;
603 }
604
605 int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
606 store_size(m);
608 if (rc == 0)
609 return MX_STATUS_ERROR;
610
611 return ops->mbox_check(m);
612}
static int execute_command(struct Mailbox *m, const char *command, const char *progress)
Run a system command.
Definition: compress.c:324
static void store_size(const struct Mailbox *m)
Save the size of the compressed file.
Definition: compress.c:181
static bool lock_realpath(struct Mailbox *m, bool excl)
Try to lock the Mailbox.realpath.
Definition: compress.c:88
static void unlock_realpath(struct Mailbox *m)
Unlock the mailbox->realpath.
Definition: compress.c:127
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1567
#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:120
Definition: mxapi.h:112
enum MxStatus(* mbox_check)(struct Mailbox *m)
Definition: mxapi.h:183
+ 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 2168 of file imap.c.

2169{
2171 enum MxStatus rc = imap_check_mailbox(m, false);
2172 /* NOTE - mv might have been changed at this point. In particular,
2173 * m could be NULL. Beware. */
2175
2176 return rc;
2177}
void imap_allow_reopen(struct Mailbox *m)
Allow re-opening a folder upon expunge.
Definition: util.c:1008
void imap_disallow_reopen(struct Mailbox *m)
Disallow re-opening a folder upon expunge.
Definition: util.c:1021
enum MxStatus imap_check_mailbox(struct Mailbox *m, bool force)
Use the NOOP or IDLE command to poll for new mail.
Definition: imap.c:1108
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()

static enum MxStatus maildir_mbox_check ( struct Mailbox m)
static

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 1169 of file maildir.c.

1170{
1171 struct stat st_new = { 0 }; /* status of the "new" subdirectory */
1172 struct stat st_cur = { 0 }; /* status of the "cur" subdirectory */
1173 int changed = MMC_NO_DIRS; /* which subdirectories have changed */
1174 bool occult = false; /* messages were removed from the mailbox */
1175 int num_new = 0; /* number of new messages added to the mailbox */
1176 bool flags_changed = false; /* message flags were changed in the mailbox */
1177 struct HashTable *fnames = NULL; /* hash table for quickly looking up the base filename
1178 for a maildir message */
1180
1181 /* XXX seems like this check belongs in mx_mbox_check() rather than here. */
1182 const bool c_check_new = cs_subset_bool(NeoMutt->sub, "check_new");
1183 if (!c_check_new)
1184 return MX_STATUS_OK;
1185
1186 struct Buffer *buf = mutt_buffer_pool_get();
1187 mutt_buffer_printf(buf, "%s/new", mailbox_path(m));
1188 if (stat(mutt_buffer_string(buf), &st_new) == -1)
1189 {
1191 return MX_STATUS_ERROR;
1192 }
1193
1194 mutt_buffer_printf(buf, "%s/cur", mailbox_path(m));
1195 if (stat(mutt_buffer_string(buf), &st_cur) == -1)
1196 {
1198 return MX_STATUS_ERROR;
1199 }
1200
1201 /* determine which subdirectories need to be scanned */
1203 changed = MMC_NEW_DIR;
1205 changed |= MMC_CUR_DIR;
1206
1207 if (changed == MMC_NO_DIRS)
1208 {
1210 return MX_STATUS_OK; /* nothing to do */
1211 }
1212
1213 /* Update the modification times on the mailbox.
1214 *
1215 * The monitor code notices changes in the open mailbox too quickly.
1216 * In practice, this sometimes leads to all the new messages not being
1217 * noticed during the SAME group of mtime stat updates. To work around
1218 * the problem, don't update the stat times for a monitor caused check. */
1219#ifdef USE_INOTIFY
1221 MonitorContextChanged = false;
1222 else
1223#endif
1224 {
1227 }
1228
1229 /* do a fast scan of just the filenames in
1230 * the subdirectories that have changed. */
1231 struct MdEmailArray mda = ARRAY_HEAD_INITIALIZER;
1232 if (changed & MMC_NEW_DIR)
1233 maildir_parse_dir(m, &mda, "new", NULL);
1234 if (changed & MMC_CUR_DIR)
1235 maildir_parse_dir(m, &mda, "cur", NULL);
1236
1237 /* we create a hash table keyed off the canonical (sans flags) filename
1238 * of each message we scanned. This is used in the loop over the
1239 * existing messages below to do some correlation. */
1241
1242 struct MdEmail *md = NULL;
1243 struct MdEmail **mdp = NULL;
1244 ARRAY_FOREACH(mdp, &mda)
1245 {
1246 md = *mdp;
1249 mutt_hash_insert(fnames, md->canon_fname, md);
1250 }
1251
1252 /* check for modifications and adjust flags */
1253 for (int i = 0; i < m->msg_count; i++)
1254 {
1255 struct Email *e = m->emails[i];
1256 if (!e)
1257 break;
1258
1259 e->active = false;
1261 md = mutt_hash_find(fnames, mutt_buffer_string(buf));
1262 if (md && md->email)
1263 {
1264 /* message already exists, merge flags */
1265 e->active = true;
1266
1267 /* check to see if the message has moved to a different
1268 * subdirectory. If so, update the associated filename. */
1269 if (!mutt_str_equal(e->path, md->email->path))
1270 mutt_str_replace(&e->path, md->email->path);
1271
1272 /* if the user hasn't modified the flags on this message, update
1273 * the flags we just detected. */
1274 if (!e->changed)
1275 if (maildir_update_flags(m, e, md->email))
1276 flags_changed = true;
1277
1278 if (e->deleted == e->trash)
1279 {
1280 if (e->deleted != md->email->deleted)
1281 {
1282 e->deleted = md->email->deleted;
1283 flags_changed = true;
1284 }
1285 }
1286 e->trash = md->email->trash;
1287
1288 /* this is a duplicate of an existing email, so remove it */
1289 email_free(&md->email);
1290 }
1291 /* This message was not in the list of messages we just scanned.
1292 * Check to see if we have enough information to know if the
1293 * message has disappeared out from underneath us. */
1294 else if (((changed & MMC_NEW_DIR) && mutt_strn_equal(e->path, "new/", 4)) ||
1295 ((changed & MMC_CUR_DIR) && mutt_strn_equal(e->path, "cur/", 4)))
1296 {
1297 /* This message disappeared, so we need to simulate a "reopen"
1298 * event. We know it disappeared because we just scanned the
1299 * subdirectory it used to reside in. */
1300 occult = true;
1301 e->deleted = true;
1302 e->purge = true;
1303 }
1304 else
1305 {
1306 /* This message resides in a subdirectory which was not
1307 * modified, so we assume that it is still present and
1308 * unchanged. */
1309 e->active = true;
1310 }
1311 }
1312
1313 /* destroy the file name hash */
1314 mutt_hash_free(&fnames);
1315
1316 /* If we didn't just get new mail, update the tables. */
1317 if (occult)
1319
1320 /* do any delayed parsing we need to do. */
1321 maildir_delayed_parsing(m, &mda, NULL);
1322
1323 /* Incorporate new messages */
1324 num_new = maildir_move_to_mailbox(m, &mda);
1325 if (num_new > 0)
1326 {
1328 m->changed = true;
1329 }
1330
1332
1333 ARRAY_FREE(&mda);
1334 if (occult)
1335 return MX_STATUS_REOPENED;
1336 if (num_new > 0)
1337 return MX_STATUS_NEW_MAIL;
1338 if (flags_changed)
1339 return MX_STATUS_FLAGS;
1340 return MX_STATUS_OK;
1341}
#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:168
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:485
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
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:1627
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:1667
@ MUTT_STAT_MTIME
File/dir's mtime - last modified time.
Definition: file.h:64
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:108
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:176
@ NT_MAILBOX_INVALID
Email list was changed.
Definition: mailbox.h:175
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:209
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
static void maildir_delayed_parsing(struct Mailbox *m, struct MdEmailArray *mda, struct Progress *progress)
This function does the second parsing pass.
Definition: maildir.c:598
#define MMC_CUR_DIR
'cur' directory changed
Definition: maildir.c:75
static void maildir_canon_filename(struct Buffer *dest, const char *src)
Generate the canonical filename for a Maildir folder.
Definition: maildir.c:726
#define MMC_NO_DIRS
No directories changed.
Definition: maildir.c:73
static 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_NEW_DIR
'new' directory changed
Definition: maildir.c:74
bool MonitorContextChanged
true after the current mailbox has changed
Definition: monitor.c:50
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
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:496
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:96
bool changed
Mailbox has been modified.
Definition: mailbox.h:110
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:132
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()

static enum MxStatus mh_mbox_check ( struct Mailbox m)
static

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 893 of file mh.c.

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

1027{
1029 if (!adata)
1030 return MX_STATUS_ERROR;
1031
1032 if (!adata->fp)
1033 {
1034 if (mbox_mbox_open(m) != MX_OPEN_OK)
1035 return MX_STATUS_ERROR;
1037 }
1038 if (!adata->fp)
1039 return MX_STATUS_ERROR;
1040
1041 struct stat st = { 0 };
1042 bool unlock = false;
1043 bool modified = false;
1044
1045 if (stat(mailbox_path(m), &st) == 0)
1046 {
1048 (st.st_size == m->size))
1049 {
1050 return MX_STATUS_OK;
1051 }
1052
1053 if (st.st_size == m->size)
1054 {
1055 /* the file was touched, but it is still the same length, so just exit */
1057 return MX_STATUS_OK;
1058 }
1059
1060 if (st.st_size > m->size)
1061 {
1062 /* lock the file if it isn't already */
1063 if (!adata->locked)
1064 {
1066 if (mbox_lock_mailbox(m, false, false) == -1)
1067 {
1069 /* we couldn't lock the mailbox, but nothing serious happened:
1070 * probably the new mail arrived: no reason to wait till we can
1071 * parse it: we'll get it on the next pass */
1072 return MX_STATUS_LOCKED;
1073 }
1074 unlock = 1;
1075 }
1076
1077 /* Check to make sure that the only change to the mailbox is that
1078 * message(s) were appended to this file. My heuristic is that we should
1079 * see the message separator at *exactly* what used to be the end of the
1080 * folder. */
1081 char buf[1024] = { 0 };
1082 if (!mutt_file_seek(adata->fp, m->size, SEEK_SET))
1083 {
1084 goto error;
1085 }
1086 if (fgets(buf, sizeof(buf), adata->fp))
1087 {
1088 if (((m->type == MUTT_MBOX) && mutt_str_startswith(buf, "From ")) ||
1089 ((m->type == MUTT_MMDF) && mutt_str_equal(buf, MMDF_SEP)))
1090 {
1091 if (!mutt_file_seek(adata->fp, m->size, SEEK_SET))
1092 {
1093 goto error;
1094 }
1095
1096 int old_msg_count = m->msg_count;
1097 if (m->type == MUTT_MBOX)
1099 else
1101
1102 if (m->msg_count > old_msg_count)
1104
1105 /* Only unlock the folder if it was locked inside of this routine.
1106 * It may have been locked elsewhere, like in
1107 * mutt_checkpoint_mailbox(). */
1108 if (unlock)
1109 {
1112 }
1113
1114 return MX_STATUS_NEW_MAIL; /* signal that new mail arrived */
1115 }
1116 else
1117 modified = true;
1118 }
1119 else
1120 {
1121 mutt_debug(LL_DEBUG1, "fgets returned NULL\n");
1122 modified = true;
1123 }
1124 }
1125 else
1126 modified = true;
1127 }
1128
1129 if (modified)
1130 {
1131 if (reopen_mailbox(m) != -1)
1132 {
1134 if (unlock)
1135 {
1138 }
1139 return MX_STATUS_REOPENED;
1140 }
1141 }
1142
1143 /* fatal error */
1144
1145error:
1147 mx_fastclose_mailbox(m, false);
1149 mutt_error(_("Mailbox was corrupted"));
1150 return MX_STATUS_ERROR;
1151}
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:706
#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:925
@ 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:61
static enum MxOpenReturns mbox_parse_mailbox(struct Mailbox *m)
Read a mailbox from disk.
Definition: mbox.c:343
static int mbox_lock_mailbox(struct Mailbox *m, bool excl, bool retry)
Lock a mailbox.
Definition: mbox.c:134
static struct MboxAccountData * mbox_adata_get(struct Mailbox *m)
Get the private data associated with a Mailbox.
Definition: mbox.c:119
static void mbox_unlock_mailbox(struct Mailbox *m)
Unlock a mailbox.
Definition: mbox.c:156
static enum MxOpenReturns mmdf_parse_mailbox(struct Mailbox *m)
Read a mailbox in MMDF format.
Definition: mbox.c:176
static int reopen_mailbox(struct Mailbox *m)
Close and reopen a mailbox.
Definition: mbox.c:531
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:429
@ 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:54
+ 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 2461 of file nntp.c.

2462{
2463 enum MxStatus rc = check_mailbox(m);
2464 if (rc == MX_STATUS_OK)
2465 {
2466 struct NntpMboxData *mdata = m->mdata;
2467 struct NntpAccountData *adata = mdata->adata;
2469 }
2470 return rc;
2471}
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 2070 of file notmuch.c.

2071{
2072 struct NmMboxData *mdata = nm_mdata_get(m);
2073 time_t mtime = 0;
2074 if (!mdata || (nm_db_get_mtime(m, &mtime) != 0))
2075 return MX_STATUS_ERROR;
2076
2077 int new_flags = 0;
2078 bool occult = false;
2079
2080 if (m->mtime.tv_sec >= mtime)
2081 {
2082 mutt_debug(LL_DEBUG2, "nm: check unnecessary (db=%lu mailbox=%lu)\n", mtime,
2083 m->mtime.tv_sec);
2084 return MX_STATUS_OK;
2085 }
2086
2087 mutt_debug(LL_DEBUG1, "nm: checking (db=%lu mailbox=%lu)\n", mtime, m->mtime.tv_sec);
2088
2089 notmuch_query_t *q = get_query(m, false);
2090 if (!q)
2091 goto done;
2092
2093 mutt_debug(LL_DEBUG1, "nm: start checking (count=%d)\n", m->msg_count);
2094 mdata->oldmsgcount = m->msg_count;
2095
2096 for (int i = 0; i < m->msg_count; i++)
2097 {
2098 struct Email *e = m->emails[i];
2099 if (!e)
2100 break;
2101
2102 e->active = false;
2103 }
2104
2105 int limit = get_limit(mdata);
2106
2107 notmuch_messages_t *msgs = get_messages(q);
2108
2109 // TODO: Analyze impact of removing this version guard.
2110#if LIBNOTMUCH_CHECK_VERSION(5, 0, 0)
2111 if (!msgs)
2112 return MX_STATUS_OK;
2113#elif LIBNOTMUCH_CHECK_VERSION(4, 3, 0)
2114 if (!msgs)
2115 goto done;
2116#endif
2117
2118 struct HeaderCache *h = nm_hcache_open(m);
2119
2120 for (int i = 0; notmuch_messages_valid(msgs) && ((limit == 0) || (i < limit));
2121 notmuch_messages_move_to_next(msgs), i++)
2122 {
2123 notmuch_message_t *msg = notmuch_messages_get(msgs);
2124 struct Email *e = get_mutt_email(m, msg);
2125
2126 if (!e)
2127 {
2128 /* new email */
2129 append_message(h, m, msg, false);
2130 notmuch_message_destroy(msg);
2131 continue;
2132 }
2133
2134 /* message already exists, merge flags */
2135 e->active = true;
2136
2137 /* Check to see if the message has moved to a different subdirectory.
2138 * If so, update the associated filename. */
2139 const char *new_file = get_message_last_filename(msg);
2140 char old_file[PATH_MAX] = { 0 };
2141 email_get_fullpath(e, old_file, sizeof(old_file));
2142
2143 if (!mutt_str_equal(old_file, new_file))
2144 update_message_path(e, new_file);
2145
2146 if (!e->changed)
2147 {
2148 /* if the user hasn't modified the flags on this message, update the
2149 * flags we just detected. */
2150 struct Email e_tmp = { 0 };
2151 e_tmp.edata = maildir_edata_new();
2152 maildir_parse_flags(&e_tmp, new_file);
2153 e_tmp.old = e->old;
2154 maildir_update_flags(m, e, &e_tmp);
2155 maildir_edata_free(&e_tmp.edata);
2156 }
2157
2158 if (update_email_tags(e, msg) == 0)
2159 new_flags++;
2160
2161 notmuch_message_destroy(msg);
2162 }
2163
2164 nm_hcache_close(h);
2165
2166 for (int i = 0; i < m->msg_count; i++)
2167 {
2168 struct Email *e = m->emails[i];
2169 if (!e)
2170 break;
2171
2172 if (!e->active)
2173 {
2174 occult = true;
2175 break;
2176 }
2177 }
2178
2179 if (m->msg_count > mdata->oldmsgcount)
2181done:
2182 if (q)
2183 notmuch_query_destroy(q);
2184
2185 nm_db_release(m);
2186
2187 m->mtime.tv_sec = mutt_date_now();
2188 m->mtime.tv_nsec = 0;
2189
2190 mutt_debug(LL_DEBUG1, "nm: ... check done [count=%d, new_flags=%d, occult=%d]\n",
2191 m->msg_count, new_flags, occult);
2192
2193 if (occult)
2194 return MX_STATUS_REOPENED;
2195 if (m->msg_count > mdata->oldmsgcount)
2196 return MX_STATUS_NEW_MAIL;
2197 if (new_flags)
2198 return MX_STATUS_FLAGS;
2199 return MX_STATUS_OK;
2200}
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:428
@ 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:810
int nm_db_get_mtime(struct Mailbox *m, time_t *mtime)
Get the database modification time.
Definition: db.c:304
int nm_db_release(struct Mailbox *m)
Close the Notmuch database.
Definition: db.c:222
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:226
static void nm_hcache_close(struct HeaderCache *h)
Close the header cache.
Definition: notmuch.c:125
static int get_limit(struct NmMboxData *mdata)
Get the database limit.
Definition: notmuch.c:398
static void append_message(struct HeaderCache *h, struct Mailbox *m, notmuch_message_t *msg, bool dedup)
Associate a message.
Definition: notmuch.c:735
static struct HeaderCache * nm_hcache_open(struct Mailbox *m)
Open a header cache.
Definition: notmuch.c:111
static notmuch_query_t * get_query(struct Mailbox *m, bool writable)
Create a new query.
Definition: notmuch.c:433
static int update_message_path(struct Email *e, const char *path)
Set the path for a message.
Definition: notmuch.c:516
static const char * get_message_last_filename(notmuch_message_t *msg)
Get a message's last filename.
Definition: notmuch.c:648
static int update_email_tags(struct Email *e, notmuch_message_t *msg)
Update the Email's tags from Notmuch.
Definition: notmuch.c:465
static notmuch_messages_t * get_messages(notmuch_query_t *query)
Load messages for a query.
Definition: notmuch.c:899
static struct Email * get_mutt_email(struct Mailbox *m, notmuch_message_t *msg)
Get the Email of a Notmuch message.
Definition: notmuch.c:701
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:88
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:52
time_t tv_sec
Number of seconds since the epoch.
Definition: file.h:51
+ 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 817 of file pop.c.

818{
819 if (!m || !m->account)
820 return MX_STATUS_ERROR;
821
823
824 const short c_pop_check_interval = cs_subset_number(NeoMutt->sub, "pop_check_interval");
825 if ((adata->check_time + c_pop_check_interval) > mutt_date_now())
826 return MX_STATUS_OK;
827
828 pop_logout(m);
829
831
832 if (pop_open_connection(adata) < 0)
833 return MX_STATUS_ERROR;
834
835 m->size = adata->size;
836
837 mutt_message(_("Checking for new messages..."));
838
839 int old_msg_count = m->msg_count;
840 int rc = pop_fetch_headers(m);
842 if (m->msg_count > old_msg_count)
844
845 if (rc < 0)
846 return MX_STATUS_ERROR;
847
848 if (rc > 0)
849 return MX_STATUS_NEW_MAIL;
850
851 return MX_STATUS_OK;
852}
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:73
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:101
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:127
POP-specific Account data -.
Definition: adata.h:37
+ Here is the call graph for this function: