Re: New procmail Maildir patches...1997-09-10 13:58:15Hi, Just in case anyone else runs into this problem: On Solaris 2.5/2.5.1 (but NOT 2.6), snprintf is only available as __snprintf. To get this patch to work happily, you need to do something like: perl -pe 's/snprintf/__snprintf/g;' <patchfile >patchfile.solaris25 Rumor has it that snprintf is named correctly in Solaris 2.6, and that Solaris <=2.4 doesn't have it at all. At 02:17 PM 9/6/97 +0000, Edward S. Marshall wrote: Well, as I promised last night on the QMail list, here's a from-scratch patch for handling Maildir mailboxes in procmail. It was inspired by Matthew Zahorik's patch (http://www.qmail.org/procmail), but does a few things that his patch failed to address: a) this version works (theoretically) with any maildir, regardless of naming, by checking for an appropriate directory tree within it. b) appropriate steps are taken to first write the file to $MAILDIR/tmp, and then move it with a link/unlink() to $MAILDIR/new, preventing potential problems. c) following the maildir(5) manpage suggestions, this patch gives a filename of <time>.<pid>.<hostname> instead of <time>.<pid>.procmail. This is important for NFS situations where you could potentially have two machines delivering mail at the same time. I've tried to ensure that MH support still works, although since I don't have MH, I can't verify if it does; if some kind soul would test whether I've completely broken MH support, I'd appreciate it. Also, this was only tested on Linux, and it compiles cleanly under Solaris 2.5.1 (both gcc and Sun's cc). For solaris, make sure you add -Dsnprintf=__snprintf to CFLAGS, or you'll get some undefined symbols warnings. There's still a few issues with this patch: a) Procmail still locks everything in sight. This is a performance hit, but it won't hurt anything, and the performance hit has always been there anyway. Low priority. b) Right now, procmail is excessively aggressive about creating a Maildir if the file in question doesn't exist. In other words, if the particular mailbox/maildir doesn't exist, a maildir is created, no questions asked. This should be configurable in some manner, but shouldn't the world really be using Maildir anyway? Medium priority. Using this is extremely easy; just reference the maildir as you would an mbox...by filename. Procmail takes responsibility for checking if the mailbox is in maildir, mh, or mbox format. Keep in mind b) above; if you reference a filename that doesn't exist, expect procmail to create a maildir by default. If you really want it to be in mbox format, touch the file. If you're into MH mailboxes, create the directory (and whatever additional magic MH mailboxes require ;-). One nice thing about this patch and the patches to Pine, for instance, is that it hides the implementation details of how the messages are stored pretty much completely from the end user. They don't need to worry about how the system is storing their messages; they can get to the business of reading their mail. Patch is included below. No warrenty on this; if it breaks, you get to keep both pieces. Don't bug Stephen R. van den Berg about this patch (unless you're bugging him to incorporate it into the main procmail distribution ;-). Mail me if you have any problems or suggestions about it. -- ____ ______ _____ _/ __ \ ___// \ Edward S. Marshall <emarshal(_at_)logic(_dot_)net> \ ___/___ \| | | \ http://www.logic.net/~emarshal/ \____\_____>__|_|__/ Information Systems Manager, Logical Solutions [ Are you a spammer looking for a great opportunity to be blacklisted? Then ] [ have your automatic bots email spam(_at_)logic(_dot_)net and secure a spot on my list! ] *** procmail-3.11pre7/src/mailfold.c.old Sat Sep 6 13:04:45 1997 --- procmail-3.11pre7/src/mailfold.c Sat Sep 6 13:47:19 1997 *************** *** 53,60 **** return ffrom?(doesc=1,(ffrom-fromw)+1L):len; /* +1 to write out the '\n' */ } long dump(s,source,len)const int s;const char*source;long len; ! { int i;long part; lasttell=i= -1;SETerrno(EBADF); if(s>=0) { if(tofile&&(lseek(s,(off_t)0,SEEK_END),fdlock(s))) --- 53,106 ---- return ffrom?(doesc=1,(ffrom-fromw)+1L):len; /* +1 to write out the '\n' */ } + static int ismaildir(chp)char*const chp; + { int fish; + struct stat blue; + char *womble; + womble=(char *)malloc(strlen(chp)+4); + fish=lstat(chp,&blue); + if(fish==-1) + { if(errno==ENOENT) + { /* We'll create a Maildir for them. */ + if(mkdir(chp,0700)==0) + { snprintf(womble,1024,"%s/new",chp); + if(mkdir(womble,0700)==0) + { snprintf(womble,1024,"%s/cur",chp); + if(mkdir(womble,0700)==0) + { snprintf(womble,1024,"%s/tmp",chp); + if(mkdir(womble,0700)==0) + { free(womble); + return 1; + } + } + } + } + free(womble); + return 0; + } + free(womble); + return 0; + } + if(S_ISDIR(blue.st_mode)) + { snprintf(womble,1024,"%s/new",chp); + if((lstat(womble,&blue)==0)&&(S_ISDIR(blue.st_mode))) + { snprintf(womble,1024,"%s/cur",chp); + if((lstat(womble,&blue)==0)&&(S_ISDIR(blue.st_mode))) + { snprintf( womble,1024,"%s/tmp",chp); + if((lstat(womble,&blue)==0)&&(S_ISDIR(blue.st_mode))) + { free(womble); + return 1; /* Woohoo. */ + } + } + } + } + /* Something is missing or screwed up. */ + free(womble); + return 0; + } + long dump(s,source,len)const int s;const char*source;long len; ! { int i;long part;char blue[1024];char *blah,*foo,*hmm; lasttell=i= -1;SETerrno(EBADF); if(s>=0) { if(tofile&&(lseek(s,(off_t)0,SEEK_END),fdlock(s))) *************** *** 97,102 **** --- 143,165 ---- i=rclose(s); } /* return an error even if nothing was to be sent */ tofile=0; + blah=strdup(buf); /* do the Maildir thing */ + foo=strrchr(blah,*MCDIRSEP_); /* yank off filename */ + if(foo&&(*(foo+1))!='\0') + { *foo='\0'; + foo=strrchr(blah,*MCDIRSEP_); /* yank off tmp */ + if(foo) + { + *foo='\0'; + if(ismaildir(blah)) + { strncpy(blue,buf,1024); + strncpy(blue+(foo-blah),"/new",4); + if(link(buf,blue)==0) + unlink(buf); /* Be safe. */ + } + } + } + free(blah); return i&&!len?-1:len; } *************** *** 162,167 **** --- 225,231 ---- /* open file or new file in directory */ static int deliver(boxname,linkfolder)char*boxname,*linkfolder; { struct stat stbuf;char*chp;int mhdir;mode_t numask; + int maildir;char fish[1024];char womble[1024]; asgnlastf=1; if(*boxname=='|'&&(!linkfolder||linkfolder==Tmnate)) { setlastfolder(boxname); *************** *** 171,177 **** --- 235,251 ---- if(boxname!=buf) strcpy(buf,boxname); /* boxname can be found back in buf */ if(*(chp=buf)) /* not null length target? */ + maildir=ismaildir(chp); + if(*chp) chp=strchr(buf,'\0')-1; /* point to just before the end */ + if(maildir) + { gethostname(womble,1024); + snprintf(fish,1024,"%s/tmp/%d.%d.%s",buf,time(NULL),getpid(),womble); + fflush(NULL); + strcpy(buf,fish); + strcpy(buf2,fish); + return opena(buf); + } mhdir=ismhdir(chp); /* is it an MH folder? */ if(!stat(boxname,&stbuf)) /* it exists */ { if(numask&&!(stbuf.st_mode&UPDATE_MASK)) -- Ivan Kohler VoiceNet Staff ivan(_at_)voicenet(_dot_)com "I ain't often right but I've never been wrong It seldom turns out the way it does in the song Once in a while you get shown the light in the strangest of places if you look at it right" -JG/RH
|
|