# DP: From: Miquel van Smoorenburg <miquels@cistron.nl>
# DP: A patch that adds support for Maildir type mailboxes.

--- ./mailcheck.c.orig	Wed Feb  4 21:30:33 1998
+++ ./mailcheck.c	Sun Nov 14 15:35:07 1999
@@ -21,8 +21,10 @@
 #include "config.h"
 
 #include <stdio.h>
+#include <errno.h>
 #include "bashtypes.h"
 #include "posixstat.h"
+#include "posixdir.h"
 #ifndef _MINIX
 #  include <sys/param.h>
 #endif
@@ -37,6 +39,8 @@
 #include "mailcheck.h"
 #include <tilde/tilde.h>
 
+#include "mailstat.c"
+
 #ifndef NOW
 #define NOW ((time_t)time ((time_t *)0))
 #endif
@@ -131,7 +135,7 @@
   struct stat finfo;
 
   file = mailfiles[i]->name;
-  if (stat (file, &finfo) == 0)
+  if (mailstat (file, &finfo) == 0)
     {
       mailfiles[i]->access_time = finfo.st_atime;
       mailfiles[i]->mod_time = finfo.st_mtime;
@@ -155,7 +159,7 @@
   i = find_mail_file (filename);
   if (i >= 0)
     {
-      if (stat (filename, &finfo) == 0)
+      if (mailstat (filename, &finfo) == 0)
 	{
 	  mailfiles[i]->mod_time = finfo.st_mtime;
 	  mailfiles[i]->access_time = finfo.st_atime;
@@ -221,7 +225,7 @@
   file = mailfiles[i]->name;
   mtime = mailfiles[i]->mod_time;
 
-  if ((stat (file, &finfo) == 0) && (finfo.st_size > 0))
+  if ((mailstat (file, &finfo) == 0) && (finfo.st_size > 0))
     return (mtime != finfo.st_mtime);
 
   return (0);
@@ -239,7 +243,7 @@
   file = mailfiles[i]->name;
   atime = mailfiles[i]->access_time;
 
-  if ((stat (file, &finfo) == 0) && (finfo.st_size > 0))
+  if ((mailstat (file, &finfo) == 0) && (finfo.st_size > 0))
     return (atime != finfo.st_atime);
 
   return (0);
@@ -257,7 +261,7 @@
   file = mailfiles[i]->name;
   size = mailfiles[i]->file_size;
 
-  return ((stat (file, &finfo) == 0) && (finfo.st_size > size));
+  return ((mailstat (file, &finfo) == 0) && (finfo.st_size > size));
 }
 
 /* Take an element from $MAILPATH and return the portion from


diff -ruN bash-2.01.1.b4/mailstat.c bash-2.01.1/mailstat.c
--- bash-2.01.1.b4/mailstat.c   Thu Jan  1 01:00:00 1970
+++ bash-2.01.1/mailstat.c      Wed Jun  2 12:05:04 1999
@@ -0,0 +1,98 @@
+/*
+ *     Stat a file. If it's a maildir, check all messages
+ *     in the maildir and present the grand total as a file.
+ *     The fields in the 'struct stat' are from the mail directory.
+ *     The following fields are emulated:
+ *
+ *     st_nlink        always 1
+ *     st_size         total number of bytes in all files
+ *     st_blocks       total number of messages
+ *     st_atime        access time of newest file in maildir
+ *     st_mtime        modify time of newest file in maildir
+ *     st_mode         S_IFDIR changed to S_IFREG
+ *
+ *     This is good enough for most mail-checking applications.
+ */
+int
+mailstat(char *path, struct stat *st)
+{
+       DIR                     *dd;
+       struct                  dirent *fn;
+       struct stat             st_ret, st_tmp;
+       static struct stat      st_new_last, st_ret_last;
+       char                    dir[PATH_MAX * 2];
+       char                    file[PATH_MAX * 2];
+       int                     i, l;
+       time_t                  atime = 0, mtime = 0;
+
+       /* First see if it's a directory. */
+       if ((i = stat(path, st)) != 0 || !S_ISDIR(st->st_mode))
+               return i;
+       if (strlen(path) > sizeof(dir) - 5) {
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+
+       st_ret = *st;
+       st_ret.st_nlink = 1;
+       st_ret.st_size  = 0;
+       st_ret.st_blocks  = 0;
+       st_ret.st_mode  &= ~S_IFDIR;
+       st_ret.st_mode  |= S_IFREG;
+
+       /* See if cur/ is present */
+       sprintf(dir, "%s/cur", path);
+       if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
+       st_ret.st_atime = st_tmp.st_atime;
+
+       /* See if tmp/ is present */
+       sprintf(dir, "%s/tmp", path);
+       if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
+       st_ret.st_mtime = st_tmp.st_mtime;
+
+       /* And new/ */
+       sprintf(dir, "%s/new", path);
+       if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
+       st_ret.st_mtime = st_tmp.st_mtime;
+
+       /* Optimization - if new/ didn't change, nothing else did. */
+       if (st_tmp.st_dev == st_new_last.st_dev &&
+           st_tmp.st_ino == st_new_last.st_ino &&
+           st_tmp.st_atime == st_new_last.st_atime &&
+           st_tmp.st_mtime == st_new_last.st_mtime) {
+               *st = st_ret_last;
+               return 0;
+       }
+       st_new_last = st_tmp;
+
+       /* Loop over new/ and cur/ */
+       for (i = 0; i < 2; i++) {
+               sprintf(dir, "%s/%s", path, i ? "cur" : "new");
+               sprintf(file, "%s/", dir);
+               l = strlen(file);
+               if ((dd = opendir(dir)) == NULL)
+                       return 0;
+               while ((fn = readdir(dd)) != NULL) {
+                       if (fn->d_name[0] == '.' ||
+                           strlen(fn->d_name) + l >= sizeof(file))
+                               continue;
+                       strcpy(file + l, fn->d_name);
+                       if (stat(file, &st_tmp) != 0)
+                               continue;
+                       st_ret.st_size += st_tmp.st_size;
+                       st_ret.st_blocks++;
+                       if (st_tmp.st_atime != st_tmp.st_mtime &&
+                           st_tmp.st_atime > atime)
+                               atime = st_tmp.st_atime;
+                       if (st_tmp.st_mtime > mtime)
+                               mtime = st_tmp.st_mtime;
+               }
+               closedir(dd);
+       }
+
+       if (atime) st_ret.st_atime = atime;
+       if (mtime) st_ret.st_mtime = mtime;
+
+       *st = st_ret_last = st_ret;
+       return 0;
+}

