Mime-Version: 1.0 Content-Type: multipart/mixed; boundary=jRHKVT23PllUwdXP From: Bruce Guenter To: djb-qmail@koobera.math.uic.edu, procmail@informatik.rwth-aachen.de Cc: Mark Wileniec Subject: Maildir patches for procmail (revised) Date: Thu, 9 Oct 1997 11:08:30 -0600 --jRHKVT23PllUwdXP Content-Type: text/plain; charset=us-ascii Greetings. Attached is a revised version of the patch to procmail to allow delivery to qmail-style maildir's. In discussion with the previous author of this patch, Edward Marshall , this patch fixes some of the problems apparent in the previous patch: - The creation of a maildir only occurs if mail would be delivered to a maildir (the filename ends with a "/"), and the directory does not exist. If a directory does exist, and it does not contain the maildir-style cur/new/tmp directories, the older mail directory behavior is used. - Some potential buffer overflow problems were corrected in creating and checking for a maildir. - the call to "dump" was moved into "deliver", to avoid the hack in "dump" to move the temporary maildir file into the new directory. For more information on qmail and maildirs, look at http://www.qmail.org/, http://www.pobox.com/~djb/qmail.html, or ftp://koobera.math.uic.edu/www/qmail.html The previous patch is currently available at: http://www.qmail.org/http://www.qmail.org/procmail-maildir-patch Summary: this patch allows procmail to attempt to deliver to qmail-style maildir's if a mailbox name ends with a directory separator (ie "/"). If the named mailbox does not exist, a maildir directory tree is created. Note: If the mailbox name does not end with a directory separator, or the named mailbox exists as a file or as a directory without the maildir-style cur/new/tmp subdirectories, delivery proceeds as it would have without this patch. As with similar software like this, this patch comes with no implied or stated warranties or guarantees. Do not annoy Stephen R. van den Berg with problems with this patch, as he did not write it. Mail me if you have any problems or suggestions about it. -- Bruce Guenter, QCC Communications Corp. Phone(work): (306)249-0220 Fax: (306)249-5128 E-Mail: bruceg@qcc.sk.ca WWW: http://www.qcc.sk.ca/~bguenter/ --jRHKVT23PllUwdXP Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="procmail-maildir.patch" diff -u --recursive procmail-3.11pre7/src/mailfold.c procmail/src/mailfold.c --- procmail-3.11pre7/src/mailfold.c Wed Apr 2 19:58:45 1997 +++ procmail/src/mailfold.c Wed Oct 8 22:52:02 1997 @@ -152,6 +152,86 @@ return -1; } +static int ckmaildir(dir,statbuf)const char*dir;struct stat*statbuf; +{ int tmplen; + char*tmpstr; + tmplen=strlen(dir)+5; + tmpstr=(char*)malloc(tmplen); + if(S_ISDIR(statbuf->st_mode)) + { snprintf(tmpstr,tmplen,"%s/new",dir); + if((lstat(tmpstr,statbuf)==0)&&(S_ISDIR(statbuf->st_mode))) + { snprintf(tmpstr,tmplen,"%s/cur",dir); + if((lstat(tmpstr,statbuf)==0)&&(S_ISDIR(statbuf->st_mode))) + { snprintf( tmpstr,tmplen,"%s/tmp",dir); + if((lstat(tmpstr,statbuf)==0)&&(S_ISDIR(statbuf->st_mode))) + { free(tmpstr); + return 1; /* Woohoo. */ + } + } + } + } + /* Something is missing or screwed up. */ + free(tmpstr); + return 0; +} + +static int mkmaildir(dir)const char* dir; +{ char *tmpstr; + int tmplen; + tmplen=strlen(dir)+5; + tmpstr=(char *)malloc(tmplen); + if(mkdir(dir,0700)==0) + { snprintf(tmpstr,tmplen,"%s/new",dir); + if(mkdir(tmpstr,0700)==0) + { snprintf(tmpstr,tmplen,"%s/cur",dir); + if(mkdir(tmpstr,0700)==0) + { snprintf(tmpstr,tmplen,"%s/tmp",dir); + if(mkdir(tmpstr,0700)==0) + { free(tmpstr); + return 1; + } + } + } + } + free(tmpstr); + return 0; +} + +static int ismaildir(chp,buf)char*const chp;char*const buf; +{ int err; + struct stat statbuf; + if(!(chp>buf&&*chp==*MCDIRSEP_)) + return 0; + err=lstat(buf,&statbuf); + if(err==-1) + return (errno==ENOENT)?mkmaildir(buf):0; + else + return ckmaildir(buf,&statbuf); +} + +static int deliver_maildir(source,len) + const char*source;const long len; +{ char path_tmp[1024];char hostname[1024];char path_new[1024];int iteration; + pid_t pid;int fd; + gethostname(hostname,1024); + pid=getpid(); + for(iteration=0; iteration<100; iteration++,sleep(2)) + {struct stat statbuf;time_t currtime; + currtime=time(NULL); + snprintf(path_tmp,1024,"%s/tmp/%d.%d.%s",buf,currtime,pid,hostname); + snprintf(path_new,1024,"%s/new/%d.%d.%s",buf,currtime,pid,hostname); + if(lstat(path_tmp, &statbuf)==0 || errno!=ENOENT) continue; + fflush(NULL); + fd=opena(path_tmp); + if(fd>0) break; + } + strcpy(buf,path_tmp); + strcpy(buf2,path_tmp); + if(dump(fd,source,len)) + return 1; + return link(path_tmp,path_new)||unlink(path_tmp); +} + static int ismhdir(chp)char*const chp; { if(chp-1>=buf&&chp[-1]==*MCDIRSEP_&&*chp==chCURDIR) { chp[-1]='\0'; @@ -160,19 +240,25 @@ return 0; } /* 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; +static int deliver(boxname,linkfolder,source,len)char*boxname,*linkfolder; + const char*source;const long len; +{ struct stat stbuf;char*chp;int mhdir;mode_t numask;int maildir; asgnlastf=1; if(*boxname=='|'&&(!linkfolder||linkfolder==Tmnate)) { setlastfolder(boxname); - return rdup(savstdout); + return dump(rdup(savstdout),source,len); } numask=UPDATE_MASK&~cumask;tofile=to_FILE; if(boxname!=buf) strcpy(buf,boxname); /* boxname can be found back in buf */ if(*(chp=buf)) /* not null length target? */ chp=strchr(buf,'\0')-1; /* point to just before the end */ + maildir=ismaildir(chp,buf); mhdir=ismhdir(chp); /* is it an MH folder? */ + if(maildir) + return deliver_maildir(source,len); + else if(!mhdir && *chp=='/') + *chp='\0'; if(!stat(boxname,&stbuf)) /* it exists */ { if(numask&&!(stbuf.st_mode&UPDATE_MASK)) chmod(boxname,stbuf.st_mode|UPDATE_MASK); @@ -184,7 +270,7 @@ { if(linkfolder) /* any leftovers? Now is the time to display them */ concatenate(linkfolder),skipped(linkfolder); tofile=strcmp(devnull,buf)?to_FOLDER:(rawnonl=1,0); - return opena(boxname); + return dump(opena(boxname),source,len); } if(linkfolder) /* any additional directories specified? */ { size_t blen; @@ -218,13 +304,13 @@ } if(linkfolder) /* free our cache */ free(linkfolder); - return fd; /* return the file descriptor we saved */ + return dump(fd,source,len); } } int writefolder(boxname,linkfolder,source,len,ignwerr)char*boxname,*linkfolder; const char*source;const long len;const int ignwerr; -{ if(dump(deliver(boxname,linkfolder),source,len)&&!ignwerr) +{ if(deliver(boxname,linkfolder,source,len)&&!ignwerr) { switch(errno) { case ENOSPC:nlog("No space left to finish writing"),logqnl(buf); break; --jRHKVT23PllUwdXP-- .