static short BuffyCount = 0; /* how many boxes with new mail */
static short BuffyNotify = 0; /* # of unnotified new boxes */
+static BUFFY* buffy_get (const char *path);
+
/* Find the last message in the file.
* upon success return 0. If no message found - return -1 */
return;
}
+static BUFFY *buffy_new (const char *path)
+{
+ BUFFY* buffy;
+
+ buffy = (BUFFY *) safe_calloc (1, sizeof (BUFFY));
+ strfcpy (buffy->path, path, sizeof (buffy->path));
+ buffy->next = NULL;
+ buffy->magic = 0;
+
+ return buffy;
+}
+
+static void buffy_free (BUFFY **mailbox)
+{
+ FREE (mailbox); /* __FREE_CHECKED__ */
+}
+
int mutt_parse_mailboxes (BUFFER *path, BUFFER *s, unsigned long data, BUFFER *err)
{
BUFFY **tmp,*tmp1;
for (tmp = &Incoming; *tmp;)
{
tmp1=(*tmp)->next;
- FREE (tmp); /* __FREE_CHECKED__ */
+ buffy_free (tmp);
*tmp=tmp1;
}
return 0;
{
if(*tmp)
{
- FREE (&((*tmp)->path));
tmp1=(*tmp)->next;
- FREE (tmp); /* __FREE_CHECKED__ */
+ buffy_free (tmp);
*tmp=tmp1;
}
continue;
}
if (!*tmp)
- {
- *tmp = (BUFFY *) safe_calloc (1, sizeof (BUFFY));
- strfcpy ((*tmp)->path, buf, sizeof ((*tmp)->path));
- (*tmp)->next = NULL;
- /* it is tempting to set magic right here */
- (*tmp)->magic = 0;
-
- }
+ *tmp = buffy_new (buf);
(*tmp)->new = 0;
(*tmp)->notified = 1;
return 0;
}
-/* people use check_mbox_size on systems where modified time attributes are
- * BADLY broken. Ignore them.
- */
-#define STAT_CHECK_SIZE (sb.st_size > tmp->size)
-#define STAT_CHECK_TIME (sb.st_mtime > sb.st_atime || (tmp->newly_created && sb.st_ctime == sb.st_mtime && sb.st_ctime == sb.st_atime))
-#define STAT_CHECK (option(OPTCHECKMBOXSIZE) ? STAT_CHECK_SIZE : STAT_CHECK_TIME)
+/* returns 1 if maildir has new mail */
+static int buffy_maildir_hasnew (BUFFY* mailbox)
+{
+ char path[_POSIX_PATH_MAX];
+ DIR *dirp;
+ struct dirent *de;
+ char *p;
+ int rc = 0;
+ struct stat sb;
+
+ snprintf (path, sizeof (path), "%s/new", mailbox->path);
+
+ /* when $mail_check_recent is set, if the new/ directory hasn't been modified since
+ * the user last exited the mailbox, then we know there is no recent mail.
+ */
+ if (option(OPTMAILCHECKRECENT))
+ {
+ if (stat(path, &sb) == 0 && sb.st_mtime < mailbox->last_visited)
+ return 0;
+ }
+
+ if ((dirp = opendir (path)) == NULL)
+ {
+ mailbox->magic = 0;
+ return 0;
+ }
+
+ while ((de = readdir (dirp)) != NULL)
+ {
+ if (*de->d_name == '.')
+ continue;
+
+ if (!(p = strstr (de->d_name, ":2,")) || !strchr (p + 3, 'T'))
+ {
+ if (option(OPTMAILCHECKRECENT))
+ {
+ char msgpath[_POSIX_PATH_MAX];
+
+ snprintf(msgpath, sizeof(msgpath), "%s/%s", path, de->d_name);
+ /* ensure this message was received since leaving this mailbox */
+ if (stat(msgpath, &sb) == 0 && (sb.st_ctime <= mailbox->last_visited))
+ continue;
+ }
+ /* one new and undeleted message is enough */
+ mailbox->new = 1;
+ rc = 1;
+ break;
+ }
+ }
+
+ closedir (dirp);
+
+ return rc;
+}
+
+/* returns 1 if mailbox has new mail */
+static int buffy_mbox_hasnew (BUFFY* mailbox, struct stat *sb)
+{
+ int rc = 0;
+ int statcheck;
+
+ if (option (OPTCHECKMBOXSIZE))
+ statcheck = sb->st_size > mailbox->size;
+ else
+ statcheck = sb->st_mtime > sb->st_atime
+ || (mailbox->newly_created && sb->st_ctime == sb->st_mtime && sb->st_ctime == sb->st_atime);
+ if (statcheck)
+ {
+ if (!option(OPTMAILCHECKRECENT) || sb->st_mtime > mailbox->last_visited)
+ {
+ rc = 1;
+ mailbox->new = 1;
+ }
+ }
+ else if (option(OPTCHECKMBOXSIZE))
+ {
+ /* some other program has deleted mail from the folder */
+ mailbox->size = (off_t) sb->st_size;
+ }
+ if (mailbox->newly_created &&
+ (sb->st_ctime != sb->st_mtime || sb->st_ctime != sb->st_atime))
+ mailbox->newly_created = 0;
+
+ return rc;
+}
int mutt_buffy_check (int force)
{
BUFFY *tmp;
struct stat sb;
- struct dirent *de;
- DIR *dirp;
- char path[_POSIX_PATH_MAX];
struct stat contex_sb;
time_t t;
#ifdef USE_IMAP
BuffyCount += imap_buffy_check (force);
-
- if (!Context || Context->magic != M_IMAP)
-#endif
-#ifdef USE_POP
- if (!Context || Context->magic != M_POP)
#endif
+
/* check device ID and serial number instead of comparing paths */
- if (!Context || !Context->path || stat (Context->path, &contex_sb) != 0)
+ if (!Context || Context->magic == M_IMAP || Context->magic == M_POP
+ || stat (Context->path, &contex_sb) != 0)
{
contex_sb.st_dev=0;
contex_sb.st_ino=0;
for (tmp = Incoming; tmp; tmp = tmp->next)
{
-#ifdef USE_IMAP
- if (tmp->magic != M_IMAP)
-#endif
- tmp->new = 0;
-
-#ifdef USE_IMAP
if (tmp->magic != M_IMAP)
{
-#endif
+ tmp->new = 0;
#ifdef USE_POP
- if (mx_is_pop (tmp->path))
- tmp->magic = M_POP;
- else
+ if (mx_is_pop (tmp->path))
+ tmp->magic = M_POP;
+ else
#endif
- if (stat (tmp->path, &sb) != 0 || (S_ISREG(sb.st_mode) && sb.st_size == 0) ||
- (!tmp->magic && (tmp->magic = mx_get_magic (tmp->path)) <= 0))
- {
- /* if the mailbox still doesn't exist, set the newly created flag to
- * be ready for when it does. */
- tmp->newly_created = 1;
- tmp->magic = 0;
- tmp->size = 0;
- continue;
- }
-#ifdef USE_IMAP
+ if (stat (tmp->path, &sb) != 0 || (S_ISREG(sb.st_mode) && sb.st_size == 0) ||
+ (!tmp->magic && (tmp->magic = mx_get_magic (tmp->path)) <= 0))
+ {
+ /* if the mailbox still doesn't exist, set the newly created flag to
+ * be ready for when it does. */
+ tmp->newly_created = 1;
+ tmp->magic = 0;
+ tmp->size = 0;
+ continue;
+ }
}
-#endif
/* check to see if the folder is the currently selected folder
* before polling */
if (!Context || !Context->path ||
-#if defined USE_IMAP || defined USE_POP
- ((
-#ifdef USE_IMAP
- tmp->magic == M_IMAP
-#endif
-#ifdef USE_POP
-#ifdef USE_IMAP
- ||
-#endif
- tmp->magic == M_POP
-#endif
- ) ? mutt_strcmp (tmp->path, Context->path) :
-#endif
- (sb.st_dev != contex_sb.st_dev || sb.st_ino != contex_sb.st_ino)
-#if defined USE_IMAP || defined USE_POP
- )
-#endif
- )
-
+ (( tmp->magic == M_IMAP || tmp->magic == M_POP )
+ ? mutt_strcmp (tmp->path, Context->path) :
+ (sb.st_dev != contex_sb.st_dev || sb.st_ino != contex_sb.st_ino)))
{
switch (tmp->magic)
{
case M_MBOX:
case M_MMDF:
-
- if (STAT_CHECK)
- {
+ if (buffy_mbox_hasnew (tmp, &sb) > 0)
BuffyCount++;
- tmp->new = 1;
- }
- else if (option(OPTCHECKMBOXSIZE))
- {
- /* some other program has deleted mail from the folder */
- tmp->size = (off_t) sb.st_size;
- }
- if (tmp->newly_created &&
- (sb.st_ctime != sb.st_mtime || sb.st_ctime != sb.st_atime))
- tmp->newly_created = 0;
-
break;
case M_MAILDIR:
-
- snprintf (path, sizeof (path), "%s/new", tmp->path);
- if ((dirp = opendir (path)) == NULL)
- {
- tmp->magic = 0;
- break;
- }
- while ((de = readdir (dirp)) != NULL)
- {
- char *p;
- if (*de->d_name != '.' &&
- (!(p = strstr (de->d_name, ":2,")) || !strchr (p + 3, 'T')))
- {
- /* one new and undeleted message is enough */
- BuffyCount++;
- tmp->new = 1;
- break;
- }
- }
- closedir (dirp);
+ if (buffy_maildir_hasnew (tmp) > 0)
+ BuffyCount++;
break;
case M_MH:
BUFFY *tmp;
char path[_POSIX_PATH_MAX];
char buffylist[2*STRING];
- int pos;
- int first;
+ size_t pos = 0;
+ int first = 1;
int have_unnotified = BuffyNotify;
- pos = 0;
- first = 1;
buffylist[0] = 0;
pos += strlen (strncat (buffylist, _("New mail in "), sizeof (buffylist) - 1 - pos)); /* __STRNCAT_CHECKED__ */
for (tmp = Incoming; tmp; tmp = tmp->next)
strfcpy (path, tmp->path, sizeof (path));
mutt_pretty_mailbox (path, sizeof (path));
- if (!first && pos + strlen (path) >= COLS - 7)
+ if (!first && (COLS - 7 >= 0) && (pos + strlen (path) >= (size_t)COLS - 7))
break;
if (!first)
return (0);
}
+void mutt_buffy_setnotified (const char *path)
+{
+ BUFFY *buffy;
+
+ buffy = buffy_get(path);
+ if (!buffy)
+ return;
+
+ buffy->notified = 1;
+ time(&buffy->last_visited);
+}
+
int mutt_buffy_notify (void)
{
if (mutt_buffy_check (0) && BuffyNotify)
/* no folders with new mail */
*s = '\0';
}
+
+/* fetch buffy object for given path, if present */
+static BUFFY* buffy_get (const char *path)
+{
+ BUFFY *cur;
+ char *epath;
+
+ if (!path)
+ return NULL;
+
+ epath = safe_strdup(path);
+ mutt_expand_path(epath, mutt_strlen(epath));
+
+ for (cur = Incoming; cur; cur = cur->next)
+ {
+ /* must be done late because e.g. IMAP delimiter may change */
+ mutt_expand_path (cur->path, sizeof (cur->path));
+ if (!mutt_strcmp(cur->path, path))
+ {
+ FREE (&epath);
+ return cur;
+ }
+ }
+
+ FREE (&epath);
+ return NULL;
+}