diff -u coolmail-1.3/Makefile coolmail+maildir-1.3/Makefile --- coolmail-1.3/Makefile Sun Sep 17 22:56:17 1995 +++ coolmail+maildir-1.3/Makefile Sun Jan 18 20:15:18 1998 @@ -24,8 +24,8 @@ # files for coolmail when you type `make install'. CFLAGS = LINK = $(CC) -INCLUDES = -I/usr/X11R5/include -LIB_DIRS = -L/usr/X11R5/lib +INCLUDES = -I/usr/X11R6/include +LIB_DIRS = -L/usr/X11R6/lib BINDIR = /usr/local/bin MANDIR = /usr/local/man/man1 @@ -34,10 +34,17 @@ AUDIO = -DAUDIO AUDIO_MODULE = audio.o +# Comment these out if you don't want Maildir support +MAILDIR = -DSUPPORT_MAILDIR +# for debugging: +#MAILDIR = $(MAILDIR) -DSUPPORT_MAILDIR_DEBUG +# normally ignores non-regular files in the Maildir; uncomment to change +#MAILDIR = $(MAILDIR) -DSUPPORT_MAILDIR_STRICTER + #### You really don't need to read past this point. #### LIBS = $(LIB_DIRS) -lXt -lX11 -lm -lXext -COPTS = $(CFLAGS) $(AUDIO) +COPTS = $(CFLAGS) $(AUDIO) $(MAILDIR) all: coolmail # Done. diff -u coolmail-1.3/audio.c coolmail+maildir-1.3/audio.c --- coolmail-1.3/audio.c Thu Sep 21 22:21:06 1995 +++ coolmail+maildir-1.3/audio.c Sun Jan 18 18:36:33 1998 @@ -128,6 +128,7 @@ INIT_FD; audiofd = open( "/dev/audio", O_WRONLY | O_NDELAY ); if (audiofd < 0) { + perror("/dev/audio"); fprintf(stderr, "%s: Problem opening /dev/audio.\n", "Coolmail"); END_FD; Only in coolmail+maildir-1.3/: coolmail diff -u coolmail-1.3/coolmail.c coolmail+maildir-1.3/coolmail.c --- coolmail-1.3/coolmail.c Thu Sep 21 22:15:50 1995 +++ coolmail+maildir-1.3/coolmail.c Sun Jan 18 20:21:42 1998 @@ -25,8 +25,10 @@ #include #include #include +#include #include + #ifdef AUDIO #include #endif @@ -35,6 +37,7 @@ #include "mailbox.h" #define DEFAULT_MAIL_DIR "/var/spool/mail/" + #define DEFAULT_COMMAND "xterm -n Elm -e mail\0" #define DEFAULT_INTERVAL 30 #define DEFAULT_FRAMES 15 @@ -104,7 +107,14 @@ return(0); /* Get the username and use it to create a default mailfile name */ - strcat(mailfile_str, cuserid(username)); +#ifdef SUPPORT_MAILDIR + if (getenv("MAILDIR") && strlen(getenv("MAILDIR"))) { + strcpy(mailfile_str,getenv("MAILDIR")); + } else if (getenv("MAIL") && strlen(getenv("MAIL"))) { + strcpy(mailfile_str,getenv("MAIL")); + } else +#endif + strcat(mailfile_str, cuserid(username)); /* Initialize the renderer */ rend_init(&argc, argv, (float)150.0); @@ -432,7 +442,7 @@ printf(" -e command Specifies a command (usually in quotes) which\n"); printf(" is used to invoke your favorite mail-reading\n"); printf(" program.\n\n"); - printf(" -f filename Watch filename, instead of the default mail\n"); + printf(" -f filename Watch filename/maildir, instead of the default mail\n"); printf(" file, %s.\n\n", DEFAULT_MAIL_DIR); printf(" -fr n Number of frames to generate for each animation.\n"); printf(" Set to an appropriate value for your machine's.\n"); @@ -626,6 +636,39 @@ /* Get file modification time */ + +/* Maildir notes (aqua@sonoma.net, Sun Jan 18 19:42:27 PST 1998): + * + * The maildir mail-storage standard is a replacement for the traditional + * 'mbox' format, intended to remove problems with file contention, locking, + * reduce corruption in the case of a program or system crash, etc, etc. + * Fairly detailed description of it can be had as part of the Qmail MTA + * documentation, http://www.qmail.org/qmail-manual-html/man5/maildir.html. + * + * The general gist of the maildir approach is that mail is stored, one + # message per file, in a subtree of ~/Maildir. New mail goes in /new, + * the "spool" goes in /cur, and /tmp is available to MUAs &c. Mail is + * theoretically supposed to be removed from /new immediately by the + * MUA, but I've observed that with mutt 0.88, at least, it isn't if + * the mailfile was generated by an import script (e.g. mbox2maildir) + * rather than the normal delivery agent, presumably due to naming + * differences. + * + * Checking for new mail mostly entails checking the mtime vs. atime of + * every file in /new, and the number of messages in /new; if the latter + * increases, new mail was delivered -- if not, but the files' atimes + * are all later than their mtimes, the MUA read the /new spool. + * + * The specifications suggest skipping over every .file, but reading all + * the others -- I've extended this to include skipping of all non-regular + * files, which seemed to make sense -- define SUPPORT_MAILDIR_STRICTER to + * override this behavior. + * + * This process is more resource-intensive than the old scheme of merely + * calling stat() for a single file -- it's an O(n) rather than O(1) + * operation. + * + */ void cool_get_inboxstatus(char *filename, int *anymail, int *unreadmail, int *newmail) { @@ -633,38 +676,119 @@ off_t newsize; struct stat st; int fd; +#ifdef SUPPORT_MAILDIR + DIR *d; + struct dirent *de; + char maildir[256],mfn[256]; +#endif - fd = open (filename, O_RDONLY, 0); - if (fd < 0) - { - *anymail = 0; - *newmail = 0; - *unreadmail = 0; - newsize = 0; - } - else - { - fstat(fd, &st); - close(fd); - newsize = st.st_size; - - if (newsize > 0) - *anymail = 1; - else - *anymail = 0; - - if (st.st_mtime >= st.st_atime && newsize > 0) - *unreadmail = 1; - else - *unreadmail = 0; - - if (newsize > oldsize && *unreadmail) - *newmail = 1; - else - *newmail = 0; - } - oldsize = newsize; +#ifdef SUPPORT_MAILDIR_DEBUG + printf("B anymail=%d, newmail=%d, unreadmail=%d, oldsize=%d, newsize=%d\n", + *anymail,*newmail,*unreadmail,oldsize,newsize); +#endif +#ifdef SUPPORT_MAILDIR + if (stat(filename,&st)==-1) { + *anymail = *newmail = *unreadmail = 0; + newsize = oldsize = 0; + perror(filename); + return; + } + if (S_ISDIR(st.st_mode)) { + /* likely a maildir */ + strcpy(maildir,filename); + if (maildir[strlen(maildir)-1]!='/') + strcat(maildir,"/"); + strcat(maildir,"new"); + if (stat(maildir,&st)==-1) { + perror(maildir); + printf("%s is not a maildir (missing/inaccessible %s)\n",filename,maildir); + *anymail = *newmail = *unreadmail = 0; + newsize = oldsize = 0; + return; + } + if (!S_ISDIR(st.st_mode)) { + printf("%s is not a directory (mode %d)\n",maildir,st.st_mode); + *anymail = *newmail = *unreadmail = 0; + newsize = oldsize = 0; + return; + } + d=opendir(maildir); + newsize=0; + *unreadmail = 0; + while ((de=readdir(d))) { + if (de->d_name[0]=='.') /* dotfiles ignored per the maildir specs */ + continue; + strcpy(mfn,maildir); + if (mfn[strlen(mfn)-1]!='/') + strcat(mfn,"/"); + strcat(mfn,de->d_name); + if (stat(mfn,&st)==-1) { + perror(mfn); + continue; + } +#ifndef SUPPORT_MAILDIR_STRICTER + if (S_ISREG(st.st_mode)) +#endif + newsize++; + if (st.st_mtime>=st.st_atime) { +#ifdef SUPPORT_MAILDIR_DEBUG + printf("unread: %s mtime = %d, atime = %d\n",de->d_name,st.st_mtime,st.st_atime); +#endif + *unreadmail = 1; + } + } + closedir(d); + if (newsize) { + *anymail = 1; + if (newsize>oldsize && *unreadmail) + *newmail = 1; + else + *newmail = 0; + } else { + *anymail = *newmail = *unreadmail = 0; + newsize = 0; + } +#ifdef SUPPORT_MAILDIR_DEBUG + printf("A anymail=%d, newmail=%d, unreadmail=%d, oldsize=%d, newsize=%d\n", + *anymail,*newmail,*unreadmail,oldsize,newsize); +#endif + oldsize=newsize; + } else { +#endif /* SUPPORT_MAILDIR */ + fd = open (filename, O_RDONLY, 0); + if (fd < 0) + { + *anymail = 0; + *newmail = 0; + *unreadmail = 0; + newsize = 0; + } + else + { + fstat(fd, &st); + close(fd); + newsize = st.st_size; + + if (newsize > 0) + *anymail = 1; + else + *anymail = 0; + + if (st.st_mtime >= st.st_atime && newsize > 0) + *unreadmail = 1; + else + *unreadmail = 0; + + if (newsize > oldsize && *unreadmail) + *newmail = 1; + else + *newmail = 0; + } +#ifdef SUPPORT_MAILDIR + } +#endif + oldsize = newsize; } /*---------------------------------------------------------------------------*/ Common subdirectories: coolmail-1.3/system and coolmail+maildir-1.3/system