ports/76137: UPDATE PORT mail/pine4: add WITH_MAILDIR flag
Lewis Thompson
purple at fajita.org
Wed Jan 12 12:00:46 UTC 2005
>Number: 76137
>Category: ports
>Synopsis: UPDATE PORT mail/pine4: add WITH_MAILDIR flag
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-ports-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Wed Jan 12 12:00:44 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator: Lewis Thompson
>Release: FreeBSD 5.3-RELEASE-p4 i386
>Organization:
>Environment:
System: FreeBSD black.fajita.org 5.3-RELEASE-p4 FreeBSD 5.3-RELEASE-p4 #0: Sun Jan 9 17:55:30 GMT 2005 lewiz at black.fajita.org:/usr/src/sys/i386/compile/BLACK i386
>Description:
This adds a WITH_MAILDIR option to allow compilation of pine4 with Maildir support.
Maildir patch from http://www.math.washington.edu/~chappa/pine/info/maildir.html
Port maintainer is CC:d.
>How-To-Repeat:
>Fix:
diff -ruN pine4.orig/Makefile pine4/Makefile
--- pine4.orig/Makefile Mon Aug 9 09:52:13 2004
+++ pine4/Makefile Wed Jan 12 11:24:06 2005
@@ -75,6 +75,11 @@
${LN} -sf ${LDAP_PREFIX}/lib ${WRKSRC}/ldap/libraries
.endif
+pre-build:
+.if defined(WITH_MAILDIR)
+ @${PATCH} ${PATCH_ARGS} -F 3 -p1 < ${PATCHDIR}/extra-patch-maildir
+.endif
+
do-build:
@(cd ${WRKSRC}; ${SETENV} ${MAKE_ENV} ./build bsf ${EXTRA_OPTS})
diff -ruN pine4.orig/files/extra-patch-maildir pine4/files/extra-patch-maildir
--- pine4.orig/files/extra-patch-maildir Thu Jan 1 01:00:00 1970
+++ pine4/files/extra-patch-maildir Wed Jan 12 11:24:06 2005
@@ -0,0 +1,2462 @@
+diff -rc pine4.61/README.maildir pine4.61.maildir/README.maildir
+*** pine4.61/README.maildir Sat Dec 11 15:12:09 2004
+--- pine4.61.maildir/README.maildir Thu Dec 2 08:13:02 2004
+***************
+*** 0 ****
+--- 1,152 ----
++ Maildir Driver for Pine4.61
++ ---------------------------
++
++ This is a maildir driver for the c-client library and Pine. This code
++ started from code in old maildir patches but it was completely rewritten,
++ so the old way to configure it does not apply anymore.
++
++ This patch takes the approach that you should not patch Pine to make the
++ maildir driver do its work correctly, by this I mean things like appending
++ messages to a folder, or so. You could of course patch Pine if you want to
++ pass parameters to the driver, but not to fix the driver. This patch
++ modifies Pine so that it will be possible to pass a parameter to the
++ driver (e.g. the location of the INBOX). Although this patch was based in
++ an old version of a maildir patch it has been almost completely rewritten
++ and it can be considered independent work (look at the flow of functions,
++ checks, etc). The patch is based on the code for the unix driver plus some
++ combinations of the mh driver and the mbx driver for the c-client library.
++ Those drivers were designed by Mark Crispin, and bugs in this code are not
++ his bugs, but my own.
++
++ One of my goals with this patch is that the associated imap server must
++ work well with this patch and any client!. Trying to do this I've cleaned
++ a lot of bugs in older work and restructured the flow. I am sure that
++ doing this is a never ending job, since improvements to the code can
++ always be made, and I am looking forward to doing them sometime in the
++ future.
++
++ This patch does not keep UIDs between sessions, but hopefully it does
++ keep consistent UIDs during one session. This is not a bug of the driver,
++ instead it is a shortcoming of the maildir specification. The main point
++ of the maildir configuration is that you should never (read my lips) ever
++ edit the message, but edit the filename associated to the message. Well, I
++ could not find any single place in the web where it was told how to save
++ the UID of a message, if there is one please let me know and I will add
++ UID support for this driver.
++
++ I got all the specification for this patch from
++ http://cr.yp.to/proto/maildir.html. If you know of a place with a better
++ specification for maildir format please let me know. The method this patch
++ uses to create a unique filename for a message is one of the "old
++ fashioned" methods. I realize that this is old fashioned, but it is
++ portable, and portability is the main reason why I decided to use an old
++ fashioned method (most methods are not portable. See the word
++ "Unfortunately" in that document).
++
++ I am interested in improving speed in the driver, please send me reports
++ of slowness or any other comments you can think are appropriate.
++
++ Once this approach was chosen, it implied the following:
++
++ * This patch assumes that your INBOX is located at "$HOME/Maildir".
++ This is a directory which should have three subdirectories "cur",
++ "tmp" and "new". Mail is delivered to 'new' and read from 'cur'. I
++ have added a configuration option "maildir-location" which can be
++ used to tell Pine where your Maildir inbox is, in case your system
++ do not use the above directory (e.g. your system may use
++ "~/.maildir"). In this case define that variable to be the name of
++ the directory where your e-mail is being delivered (e.g.
++ ".maildir").
++
++ * If you want to use the above configuration as your inbox, you must
++ define your inbox-path as "#md/inbox" (no quotes). You can define
++ the inbox-path like above even if you have changed the
++ maildir-location variable. That's the whole point of that variable.
++
++ * You can create a collection of folders which are in maildir format.
++ In order to do that press M S L and add the following data:
++
++ Nickname: Anything
++ Server :
++ Path : #md/relative/path/to/home
++ View :
++
++ Written by Eduardo Chappa <chappa at math.washington.edu>
++
++ Last Updated June 04, 2004
++ Maildir Driver for Pine4.61
++ ---------------------------
++
++ This is a maildir driver for the c-client library and Pine. This code
++ started from code in old maildir patches but it was completely rewritten,
++ so the old way to configure it does not apply anymore.
++
++ This patch takes the approach that you should not patch Pine to make the
++ maildir driver do its work correctly, by this I mean things like appending
++ messages to a folder, or so. You could of course patch Pine if you want to
++ pass parameters to the driver, but not to fix the driver. This patch
++ modifies Pine so that it will be possible to pass a parameter to the
++ driver (e.g. the location of the INBOX). Although this patch was based in
++ an old version of a maildir patch it has been almost completely rewritten
++ and it can be considered independent work (look at the flow of functions,
++ checks, etc). The patch is based on the code for the unix driver plus some
++ combinations of the mh driver and the mbx driver for the c-client library.
++ Those drivers were designed by Mark Crispin, and bugs in this code are not
++ his bugs, but my own.
++
++ One of my goals with this patch is that the associated imap server must
++ work well with this patch and any client!. Trying to do this I've cleaned
++ a lot of bugs in older work and restructured the flow. I am sure that
++ doing this is a never ending job, since improvements to the code can
++ always be made, and I am looking forward to doing them sometime in the
++ future.
++
++ This patch does not keep UIDs between sessions, but hopefully it does
++ keep consistent UIDs during one session. This is not a bug of the driver,
++ instead it is a shortcoming of the maildir specification. The main point
++ of the maildir configuration is that you should never (read my lips) ever
++ edit the message, but edit the filename associated to the message. Well, I
++ could not find any single place in the web where it was told how to save
++ the UID of a message, if there is one please let me know and I will add
++ UID support for this driver.
++
++ I got all the specification for this patch from
++ http://cr.yp.to/proto/maildir.html. If you know of a place with a better
++ specification for maildir format please let me know. The method this patch
++ uses to create a unique filename for a message is one of the "old
++ fashioned" methods. I realize that this is old fashioned, but it is
++ portable, and portability is the main reason why I decided to use an old
++ fashioned method (most methods are not portable. See the word
++ "Unfortunately" in that document).
++
++ I am interested in improving speed in the driver, please send me reports
++ of slowness or any other comments you can think are appropriate.
++
++ Once this approach was chosen, it implied the following:
++
++ * This patch assumes that your INBOX is located at "$HOME/Maildir".
++ This is a directory which should have three subdirectories "cur",
++ "tmp" and "new". Mail is delivered to 'new' and read from 'cur'. I
++ have added a configuration option "maildir-location" which can be
++ used to tell Pine where your Maildir inbox is, in case your system
++ do not use the above directory (e.g. your system may use
++ "~/.maildir"). In this case define that variable to be the name of
++ the directory where your e-mail is being delivered (e.g.
++ ".maildir").
++
++ * If you want to use the above configuration as your inbox, you must
++ define your inbox-path as "#md/inbox" (no quotes). You can define
++ the inbox-path like above even if you have changed the
++ maildir-location variable. That's the whole point of that variable.
++
++ * You can create a collection of folders which are in maildir format.
++ In order to do that press M S L and add the following data:
++
++ Nickname: Anything
++ Server :
++ Path : #md/relative/path/to/home
++ View :
++
++ Written by Eduardo Chappa <chappa at math.washington.edu>
++
++ Last Updated June 04, 2004
+diff -rc pine4.61/imap/src/c-client/mail.h pine4.61.maildir/imap/src/c-client/mail.h
+*** pine4.61/imap/src/c-client/mail.h Mon Jun 21 18:06:58 2004
+--- pine4.61.maildir/imap/src/c-client/mail.h Thu Dec 2 08:13:10 2004
+***************
+*** 307,312 ****
+--- 307,314 ----
+ #define SET_SNARFINTERVAL (long) 565
+ #define GET_SNARFPRESERVE (long) 566
+ #define SET_SNARFPRESERVE (long) 567
++ #define GET_MDINBOX (long) 568
++ #define SET_MDINBOX (long) 569
+
+ /* Driver flags */
+
+***************
+*** 785,790 ****
+--- 787,793 ----
+ unsigned int spare7 : 1; /* seventh spare bit */
+ unsigned int spare8 : 1; /* eighth spare bit */
+ void *sparep; /* spare pointer */
++ void *maildirp; /* for the Maildir driver, can't use sparep */
+ unsigned long user_flags; /* user-assignable flags */
+ } MESSAGECACHE;
+
+diff -rc pine4.61/imap/src/osdep/unix/Makefile pine4.61.maildir/imap/src/osdep/unix/Makefile
+*** pine4.61/imap/src/osdep/unix/Makefile Tue Jun 22 13:56:05 2004
+--- pine4.61.maildir/imap/src/osdep/unix/Makefile Wed Nov 24 15:15:18 2004
+***************
+*** 107,113 ****
+ # Standard distribution build parameters
+
+ DEFAULTAUTHENTICATORS=md5 pla log
+! DEFAULTDRIVERS=imap nntp pop3 mh mx mbx tenex mtx mmdf unix news phile
+
+
+ # Normally no need to change any of these
+--- 107,113 ----
+ # Standard distribution build parameters
+
+ DEFAULTAUTHENTICATORS=md5 pla log
+! DEFAULTDRIVERS=maildir imap nntp pop3 mh mx mbx tenex mtx mmdf unix news phile
+
+
+ # Normally no need to change any of these
+***************
+*** 116,122 ****
+ BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o siglocal.o \
+ dummy.o pseudo.o netmsg.o flstring.o fdstring.o \
+ rfc822.o nntp.o smtp.o imap4r1.o pop3.o \
+! unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o
+ CFLAGS=-g
+
+ CAT=cat
+--- 116,122 ----
+ BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o siglocal.o \
+ dummy.o pseudo.o netmsg.o flstring.o fdstring.o \
+ rfc822.o nntp.o smtp.o imap4r1.o pop3.o \
+! unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o maildir.o
+ CFLAGS=-g
+
+ CAT=cat
+***************
+*** 245,251 ****
+
+ cyg: # Cygwin - note that most local file drivers don't work!!
+ $(BUILD) `$(CAT) SPECIALS` OS=$@ \
+! DEFAULTDRIVERS="imap nntp pop3 mbx unix phile" \
+ SIGTYPE=psx CHECKPW=cyg LOGINPW=cyg CRXTYPE=std \
+ SPOOLDIR=/var \
+ ACTIVEFILE=/usr/local/news/lib/active \
+--- 245,251 ----
+
+ cyg: # Cygwin - note that most local file drivers don't work!!
+ $(BUILD) `$(CAT) SPECIALS` OS=$@ \
+! DEFAULTDRIVERS="imap nntp pop3 mbx unix maildir phile" \
+ SIGTYPE=psx CHECKPW=cyg LOGINPW=cyg CRXTYPE=std \
+ SPOOLDIR=/var \
+ ACTIVEFILE=/usr/local/news/lib/active \
+***************
+*** 834,840 ****
+ tenex.o: mail.h misc.h osdep.h dummy.h
+ unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h
+ utf8.o: mail.h misc.h osdep.h utf8.h
+!
+
+ # OS-dependent
+
+--- 834,840 ----
+ tenex.o: mail.h misc.h osdep.h dummy.h
+ unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h
+ utf8.o: mail.h misc.h osdep.h utf8.h
+! maildir.o: mail.h misc.h osdep.h maildir.h dummy.h
+
+ # OS-dependent
+
+diff -rc pine4.61/imap/src/osdep/unix/dummy.c pine4.61.maildir/imap/src/osdep/unix/dummy.c
+*** pine4.61/imap/src/osdep/unix/dummy.c Mon Feb 2 16:50:32 2004
+--- pine4.61.maildir/imap/src/osdep/unix/dummy.c Wed Nov 24 15:15:18 2004
+***************
+*** 104,109 ****
+--- 104,111 ----
+ {
+ char *s,tmp[MAILTMPLEN];
+ struct stat sbuf;
++
++ maildir_remove_root(&name);
+ /* must be valid local mailbox */
+ if (name && *name && (*name != '{') && (s = mailboxfile (tmp,name))) {
+ /* indeterminate clearbox INBOX */
+***************
+*** 362,368 ****
+ char *s,tmp[MAILTMPLEN];
+ /* don't \NoSelect dir if it has a driver */
+ if ((attributes & LATT_NOSELECT) && (d = mail_valid (NIL,name,NIL)) &&
+! (d != &dummydriver)) attributes &= ~LATT_NOSELECT;
+ if (!contents || /* notify main program */
+ (!(attributes & LATT_NOSELECT) && (csiz = strlen (contents)) &&
+ (s = dummy_file (tmp,name)) && !stat (s,&sbuf) &&
+--- 364,373 ----
+ char *s,tmp[MAILTMPLEN];
+ /* don't \NoSelect dir if it has a driver */
+ if ((attributes & LATT_NOSELECT) && (d = mail_valid (NIL,name,NIL)) &&
+! (d != &dummydriver)){
+! attributes &= ~LATT_NOSELECT;
+! attributes |= LATT_NOINFERIORS;
+! }
+ if (!contents || /* notify main program */
+ (!(attributes & LATT_NOSELECT) && (csiz = strlen (contents)) &&
+ (s = dummy_file (tmp,name)) && !stat (s,&sbuf) &&
+***************
+*** 382,387 ****
+--- 387,394 ----
+ {
+ char *s,tmp[MAILTMPLEN];
+ long ret = NIL;
++ if(!strncmp(mailbox,"#md/",4))
++ return maildir_create(stream, mailbox);
+ /* validate name */
+ if (!(compare_cstring (mailbox,"INBOX") && (s = dummy_file (tmp,mailbox)))) {
+ sprintf (tmp,"Can't create %.80s: invalid name",mailbox);
+***************
+*** 447,452 ****
+--- 454,461 ----
+ {
+ struct stat sbuf;
+ char *s,tmp[MAILTMPLEN];
++ if (!strncmp(mailbox,"#md/",4))
++ return maildir_delete(stream, mailbox);
+ if (!(s = dummy_file (tmp,mailbox))) {
+ sprintf (tmp,"Can't delete - invalid name: %.80s",s);
+ MM_LOG (tmp,ERROR);
+***************
+*** 473,478 ****
+--- 482,490 ----
+ {
+ struct stat sbuf;
+ char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN];
++
++ maildir_remove_root(&old);
++ maildir_remove_root(&newname);
+ /* no trailing / allowed */
+ if (!dummy_file (oldname,old) || !(s = dummy_file (mbx,newname)) ||
+ ((s = strrchr (s,'/')) && !s[1])) {
+diff -rc pine4.61/imap/src/osdep/unix/env_unix.c pine4.61.maildir/imap/src/osdep/unix/env_unix.c
+*** pine4.61/imap/src/osdep/unix/env_unix.c Thu Jul 8 15:02:04 2004
+--- pine4.61.maildir/imap/src/osdep/unix/env_unix.c Wed Nov 24 15:15:18 2004
+***************
+*** 33,38 ****
+--- 33,39 ----
+ static char *sysInbox = NIL; /* system inbox name */
+ static char *newsActive = NIL; /* news active file */
+ static char *newsSpool = NIL; /* news spool */
++ static char *myMdInboxDir = NIL;/* Location of the Maildir INBOX */
+ /* anonymous home directory */
+ static char *anonymousHome = NIL;
+ static char *ftpHome = NIL; /* ftp export home directory */
+***************
+*** 177,182 ****
+--- 178,189 ----
+ case GET_NEWSRC:
+ ret = (void *) myNewsrc;
+ break;
++ case SET_MDINBOX:
++ if (myMdInboxDir) fs_give ((void **) &myMdInboxDir);
++ myMdInboxDir = cpystr ((char *) value);
++ case GET_MDINBOX:
++ ret = (void *) myMdInboxDir;
++ break;
+ case SET_NEWSACTIVE:
+ if (newsActive) fs_give ((void **) &newsActive);
+ newsActive = cpystr ((char *) value);
+***************
+*** 733,738 ****
+--- 740,746 ----
+ }
+ if (!myLocalHost) mylocalhost ();
+ if (!myNewsrc) myNewsrc = cpystr(strcat (strcpy (tmp,myHomeDir),"/.newsrc"));
++ if (!myMdInboxDir) myMdInboxDir = cpystr("Maildir");
+ if (!newsActive) newsActive = cpystr (ACTIVEFILE);
+ if (!newsSpool) newsSpool = cpystr (NEWSSPOOL);
+ /* force default prototype to be set */
+diff -rc pine4.61/imap/src/osdep/unix/maildir.c pine4.61.maildir/imap/src/osdep/unix/maildir.c
+*** pine4.61/imap/src/osdep/unix/maildir.c Sat Dec 11 15:12:09 2004
+--- pine4.61.maildir/imap/src/osdep/unix/maildir.c Mon Dec 6 08:44:51 2004
+***************
+*** 0 ****
+--- 1,1659 ----
++ /*
++ * Maildir driver for Pine4.61
++ *
++ * Written by Eduardo Chappa <chappa at math.washington.edu>
++ * Last Update: December 06, 2004.
++ *
++ * The IMAP toolkit provided in this Distribution is
++ * Copyright 2004 University of Washington.
++ * The full text of our legal notices is contained in the file called
++ * CPYRIGHT, included with this Distribution.
++ */
++
++ #include <stdio.h>
++ #include <ctype.h>
++ #include <errno.h>
++ extern int errno; /* just in case */
++ #include "mail.h"
++ #include "osdep.h"
++ #include <pwd.h>
++ #include <sys/stat.h>
++ #include <sys/time.h>
++ #include "maildir.h"
++ #include "fdstring.h"
++ #include "misc.h"
++ #include "dummy.h"
++
++ /* Driver dispatch used by MAIL */
++
++ DRIVER maildirdriver = {
++ "md", /* driver name, yes it's md, not maildir */
++ /* driver flags */
++ DR_MAIL|DR_LOCAL|DR_NOFAST|DR_NAMESPACE|DR_NOSTICKY,
++ (DRIVER *) NIL, /* next driver */
++ maildir_valid, /* mailbox is valid for us */
++ maildir_parameters, /* manipulate parameters */
++ NIL, /* scan mailboxes */
++ maildir_list, /* find mailboxes */
++ maildir_lsub, /* find subscribed mailboxes */
++ maildir_sub, /* subscribe to mailbox */
++ maildir_unsub, /* unsubscribe from mailbox */
++ maildir_create, /* create mailbox */
++ maildir_delete, /* delete mailbox */
++ maildir_rename, /* rename mailbox */
++ mail_status_default, /* status of mailbox */
++ maildir_open, /* open mailbox */
++ maildir_close, /* close mailbox */
++ NIL, /* fetch message "fast" attributes */
++ NIL, /* fetch message flags */
++ NIL, /* fetch overview */
++ NIL, /* fetch message structure */
++ maildir_header, /* fetch message header */
++ maildir_text, /* fetch message body */
++ NIL, /* fetch partial message text */
++ NIL, /* unique identifier */
++ NIL, /* message number */
++ NIL, /* modify flags */
++ maildir_flagmsg, /* per-message modify flags */
++ NIL, /* search for message based on criteria */
++ NIL, /* sort messages */
++ NIL, /* thread messages */
++ maildir_ping, /* ping mailbox to see if still alive */
++ maildir_check, /* check for new messages */
++ maildir_expunge, /* expunge deleted messages */
++ maildir_copy, /* copy messages to another mailbox */
++ maildir_append, /* append string message to mailbox */
++ NIL /* garbage collect stream */
++ };
++
++ MAILSTREAM maildirproto = {&maildirdriver}; /* prototype stream */
++
++ void
++ md_domain_name(void)
++ {
++ int i;
++
++ strcpy(mdlocaldomain,mylocalhost ());
++ for (i = 0; mdlocaldomain[i] ; i++)
++ if(mdlocaldomain[i] == '/')
++ mdlocaldomain[i] = '\057';
++ else if (mdlocaldomain[i] == ':')
++ mdlocaldomain[i] = '\072';
++ }
++
++ /* remove the "#md/" part from a folder name */
++ void maildir_remove_root (char **name)
++ {
++ if (maildir_valid_name(*name)){
++ (*name) += 3;
++ if (**name == '/')
++ (*name)++;
++ }
++ }
++
++
++ /* Check validity of the name, we accept:
++ * a) #md/directory/folder
++ * b) #md/inbox
++ * A few considerations: We can only accept as valid
++ * a) names that start with #md/ and the directory exists or
++ * b) names that do not start with #md/ but are maildir directories (have
++ * the /cur, /tmp and /new structure)
++ */
++
++
++ int maildir_valid_name (char *name)
++ {
++ int ret = NIL;
++ char tmpname[MAILTMPLEN+1] = {'\0'};
++
++ if (mdfpath)
++ fs_give((void **)&mdfpath);
++ if (name && name[0] != '#')
++ sprintf(tmpname,"#md/%s",name);
++ mdfpath = cpystr(tmpname[0] ? tmpname : name);
++
++ if (name && (name[0] == '#')
++ && ((name[1] == 'm') || (name[1] == 'M'))
++ && ((name[2] == 'd') || (name[2] == 'D'))
++ && ((name[3] == '/') && name[4])) ret = T;
++
++ return ret;
++ }
++
++ /* Check if the directory whose path is given by name is a valid maildir
++ * directory (contains /cur, /tmp and /new)
++ */
++
++ int maildir_valid_dir (char *name)
++ {
++ int len;
++ DirNamesType i;
++ struct stat sbuf;
++ char tmp[MAILTMPLEN+1];
++
++ len = strlen(name);
++ for (i = Cur; i != EndDir; i++){
++ MDFLD(tmp, name, i);
++ if (stat(tmp, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode))
++ break;
++ }
++ name[len] = '\0';
++ return i == EndDir ? T : NIL;
++ }
++
++ /* given a maildir folder, return its path. Memory freed by caller. Directory
++ * does not contain the trailing slash "/". On error NULL is returned.
++ */
++
++ int maildir_file_path (char *name, char *tmp)
++ {
++ char *maildirpath = mail_parameters(NIL,GET_MDINBOX,NIL);
++
++ maildir_remove_root(&name);
++ tmp[0] = '\0'; /* just in case something fails */
++ if (strlen(myhomedir()) +
++ max(strlen(name), strlen(maildirpath
++ ? maildirpath : "Maildir")) > MAILTMPLEN){
++ errno = ENAMETOOLONG;
++ sprintf(tmp,"Error opening \"%s\": %s", name, strerror (errno));
++ mm_log(tmp,ERROR);
++ }
++ else
++ sprintf (tmp,"%s/%s%s",myhomedir (),
++ strncmp (ucase (strcpy (tmp, name)), "INBOX", 5)
++ ? name : (maildirpath ? maildirpath : "Maildir") ,
++ strncmp (ucase (strcpy (tmp, name)), "INBOX", 5)
++ ? "" : *(name+5) == '/' ? name+5 : "");
++
++ return tmp[0] ? T : NIL;
++ }
++
++ /* Check validity of mailbox. This routine does not send errors to log, other
++ * routines calling this one may do so, though
++ */
++
++ DRIVER *maildir_valid (char *name)
++ {
++ char tmpname[MAILTMPLEN+1];
++ struct stat sbuf;
++ int rv, mdv, mdvd;
++
++ maildir_file_path(name, tmpname);
++ mdv = maildir_valid_name(name);
++ mdvd = maildir_valid_dir(tmpname);
++ rv = stat(tmpname, &sbuf);
++
++ return (mdv == 1 && rv == 0 && S_ISDIR(sbuf.st_mode) && mdvd == 1)
++ || (mdv == 1 && rv < 0 && errno == ENOENT)
++ || (mdv == 0 && mdvd == 1) ? &maildirdriver : NIL;
++ }
++
++ int maildir_base_name(char *name, char *tmp)
++ {
++ int i;
++
++ if (tmp)
++ *tmp = '\0';
++
++ if (!name || name[0] == '.')
++ return NIL;
++
++ for (i = 0; name[i] && name[i] != FLAGSEP && (tmp[i] = name[i]); i++);
++ tmp[i] = '\0'; /* tie me off, thank you */
++
++ return T;
++ }
++
++ /*
++ * return all files in a given directory. This is a separate call
++ * so that if there are warnings during compilation this only appears once
++ * It is also important to touch the uidvalidity file to tell us when we did
++ * this last.
++ */
++ unsigned long
++ maildir_scandir (char *name, struct direct ***flist,
++ unsigned long *nfiles, int *scand)
++ {
++ struct stat sbuf;
++
++ if (scand)
++ *scand = -1; /* assume error for safety */
++ stat(name,&sbuf); /* stat the containing directory */
++ if (scand)
++ *scand = scandir(name, flist, maildir_select, maildir_namesort);
++ *nfiles = (scand && (*scand > 0)) ? (unsigned long) *scand : 0L;
++
++ return sbuf.st_ctime;
++ }
++
++ /* Does a message with given name exists (or was it removed)?
++ * Returns: 1 - yes, such message exist,
++ * 0 - No, that message does not exist anymore
++ *
++ * Parameters: stream, name of mailbox, new name if his message does not
++ * exist.
++ */
++
++ int maildir_message_exists(MAILSTREAM *stream, char *name, char *newfile)
++ {
++ char tmp[MAILTMPLEN+1];
++ int gotit = NIL;
++ DIR *dir;
++ struct direct *d;
++ struct stat sbuf;
++
++ /* First check directly if it exists, if not there, look for it */
++ sprintf(tmp,"%s/%s", LOCAL->curdir, name);
++ if ((stat(tmp, &sbuf) == 0) && ((sbuf.st_mode & S_IFMT) == S_IFREG))
++ return T;
++
++ if (!(dir = opendir (LOCAL->curdir)))
++ return NIL;
++
++ while ((d = readdir(dir)) && gotit == NIL){
++ if (d->d_name[0] == '.')
++ continue;
++ if (same_maildir_file(d->d_name, name)){
++ gotit = T;
++ strcpy(newfile, d->d_name);
++ }
++ }
++ closedir(dir);
++ return gotit;
++ }
++
++ /* Maildir open */
++
++ MAILSTREAM *maildir_open (MAILSTREAM *stream)
++ {
++ char tmp[MAILTMPLEN+1], tmp2[MAILTMPLEN+1];
++ struct stat sbuf;
++
++ if (!stream) return &maildirproto;
++ if (stream->local) fatal ("maildir recycle stream");
++ md_domain_name(); /* get domain name for maildir files in mdlocaldomain */
++ stream->uid_last = stream->uid_validity = 0;
++ if (!stream->rdonly){
++ stream->perm_seen = stream->perm_deleted = stream->perm_flagged =
++ stream->perm_answered = stream->perm_draft = T;
++ }
++ stream->uid_validity = time(0);
++ stream->local = (MAILDIRLOCAL *)fs_get (sizeof (MAILDIRLOCAL));
++ memset(LOCAL, 0, sizeof(MAILDIRLOCAL));
++ LOCAL->fd = -1;
++
++ strcpy(tmp2, stream->mailbox); /* tmp2 = what the user entered */
++ if (maildir_file_path("#md/INBOX", tmp)) /* tmp = real path to #md/inbox */
++ LOCAL->inbox = !strcmp(ucase(tmp2),"#MD/INBOX") || !strcmp(tmp2,tmp);
++
++ strcpy(tmp, stream->mailbox);
++ if (maildir_file_path (stream->mailbox, tmp))
++ LOCAL->dir = cpystr (tmp);
++ if (LOCAL->dir){
++ MDFLD(tmp, LOCAL->dir, Cur);
++ LOCAL->curdir = cpystr (tmp);
++ if (stat (LOCAL->curdir,&sbuf) < 0) {
++ sprintf (tmp,"Can't open folder %s: %s",
++ stream->mailbox,strerror (errno));
++ mm_log (tmp,ERROR);
++ maildir_close(stream, 0);
++ return NIL;
++ }
++ }
++ sprintf(tmp,"%s/%s", *stream->mailbox == '/' ? "" : myhomedir(),
++ stream->mailbox);
++ fs_give ((void **) &stream->mailbox);
++ stream->mailbox = cpystr(tmp);
++
++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = MAXMESSAGESIZE) + 1);
++ stream->sequence++;
++ stream->nmsgs = stream->recent = 0;
++
++ maildir_parse_folder(stream, 1);
++
++ return stream;
++ }
++
++ /* Maildir initial parsing of the folder */
++ void
++ maildir_parse_folder (MAILSTREAM *stream, int full)
++ {
++ unsigned long total;
++
++ if (!stream) /* what??? */
++ return;
++
++ MM_CRITICAL(stream);
++
++ /* Scan old messages first, escoba! */
++ total = LOCAL ? maildir_parse_dir(stream, 0L, Cur, full)
++ : stream->nmsgs;
++ stream->nmsgs = LOCAL ? maildir_parse_dir(stream, total, New, full)
++ : stream->nmsgs;
++
++ MM_NOCRITICAL(stream);
++ }
++
++ /* Return the number of messages in the directory, while filling the
++ * elt structure.
++ */
++
++ unsigned long
++ maildir_parse_dir(MAILSTREAM *stream, unsigned long nmsgs,
++ DirNamesType dirtype, int full)
++ {
++ char tmp[MAILTMPLEN+1], tmp2[MAILTMPLEN+1], file[MAILTMPLEN+1],
++ newfile[MAILTMPLEN+1], *mdstr;
++ struct direct **names = NIL;
++ struct stat sbuf;
++ unsigned long i, j = 0L, nfiles, last_scan;
++ unsigned long recent = stream ? stream->recent : 0L;
++ int d = 0, f = 0, r = 0, s = 0, t = 0;
++ int k, we_compute, in_list, scan_err;
++ int silent = stream ? stream->silent : NIL;
++ MESSAGECACHE *elt;
++
++ MDFLD(tmp, LOCAL->dir, dirtype);
++ if (access (tmp, R_OK|W_OK|X_OK) != 0){
++ maildir_abort(stream);
++ return stream->nmsgs;
++ }
++
++ MDFLD(tmp, LOCAL->dir, Cur);
++ if (dirtype != New &&
++ (stat(tmp, &sbuf) < 0 || sbuf.st_ctime == LOCAL->scantime))
++ return stream->nmsgs;
++
++ MDFLD(tmp, LOCAL->dir, dirtype);
++ last_scan = maildir_scandir (tmp, &names, &nfiles, &scan_err);
++ if (dirtype == Cur)
++ LOCAL->scantime = last_scan;
++
++ if (scan_err < 0){
++ maildir_abort(stream);
++ return nmsgs;
++ }
++
++ if (dirtype == Cur)
++ for (i = 1L; i <= stream->nmsgs;){
++ elt = mail_elt(stream, i);
++ in_list = elt && elt->maildirp && nfiles > 0L
++ ? (MDPOS(elt) < nfiles
++ ? same_maildir_file(MDFILE(elt), names[MDPOS(elt)]->d_name)
++ : NIL)
++ || maildir_message_in_list(MDFILE(elt), names, 0L,
++ nfiles - 1L, &MDPOS(elt))
++ : NIL;
++ if (!in_list){
++ if (elt->maildirp)
++ maildir_free_file ((void **) &elt->maildirp);
++
++ if (elt->recent) --recent;
++ mail_expunged(stream,i);
++ }
++ else i++;
++ }
++
++ stream->silent = T;
++ for (we_compute = 0, i = 1L; i <= nfiles; i++){
++ unsigned long pos, n;
++ mail_exists(stream, i + nmsgs);
++ elt = mail_elt(stream, i + nmsgs);
++ if (elt && elt->maildirp)
++ pos = MDPOS(elt); /* use data we found above */
++ else{
++ if (full)
++ pos = i - 1; /* first time, use sequence number */
++ else{
++ for (n = 0L ; (n < nfiles) && !names[n] ; n++);
++ pos = n; /* nfiles > stream->nmsgs!!, assign one */
++ }
++ }
++ if (dirtype == New) elt->recent = T;
++ if (!elt->private.uid){
++ elt->private.uid = stream->uid_last + 1;
++ stream->uid_validity = time(0);
++ }
++ if (stream->uid_last < elt->private.uid)
++ stream->uid_last = elt->private.uid;
++ if (elt->maildirp || stream->rdonly){
++ we_compute++; /* get old flags */
++ maildir_getflag(names[pos]->d_name, &d, &f, &r ,&s, &t);
++ maildir_free_file_only ((void **)&elt->maildirp);
++ }
++ if (!elt->maildirp)
++ maildir_get_file(&elt->maildirp);
++ MDFILE(elt) = cpystr(names[pos]->d_name);
++ MDPOS(elt) = pos;
++ if (full && !stream->rdonly)
++ maildir_parse_message(stream, i+nmsgs, dirtype);
++
++ if (we_compute && (elt->draft != d || elt->flagged != f ||
++ elt->answered != r || elt->seen != s || elt->deleted != t)){
++ elt->draft = d; elt->flagged = f; elt->answered = r;
++ elt->seen = s; elt->deleted = t;
++ if (!stream->rdonly)
++ MM_FLAGS(stream, i+nmsgs);
++ }
++ if (dirtype == New && !stream->rdonly){ /* move new messages to cur */
++ sprintf (file,"%s/%s", tmp, names[pos]->d_name);
++ if (stat (file,&sbuf) == 0 && S_ISREG (sbuf.st_mode)){
++ strcpy(tmp2,names[pos]->d_name);
++ if ((mdstr = strstr (names[pos]->d_name,MDSEP(3)))
++ || (mdstr = strstr (names[pos]->d_name,MDSEP(2)))){ /* Grrr */
++ *(mdstr+1) = '2';
++ sprintf (newfile,"%s/%s",LOCAL->curdir,names[pos]->d_name);
++ }
++ else{
++ sprintf (newfile,"%s/%s%s",LOCAL->curdir,names[pos]->d_name,MDSEP(2));
++ strcat(tmp2, MDSEP(2));
++ }
++ if (link (file,newfile) < 0){
++ mm_log("Unable to read new mail!",WARN);
++ }
++ else{
++ unlink (file);
++ j++; /* success!, count it! */
++ }
++ maildir_free_file_only((void **)&elt->maildirp);
++ MDFILE(elt) = cpystr(tmp2);
++ MDSIZE(elt) = sbuf.st_size;
++ MDMTIME(elt) = sbuf.st_mtime;
++ maildir_get_date(stream, i + nmsgs, New);
++ }
++ }
++ fs_give((void **)&names[pos]);
++ }
++ if(names)
++ fs_give((void **) &names);
++ stream->silent = silent;
++ if (dirtype == New && stream->rdonly)
++ j = nfiles;
++ mail_exists(stream, nmsgs + (dirtype == New ? j : nfiles));
++ mail_recent(stream, recent + (dirtype == New ? j : 0));
++
++ return (nmsgs + (dirtype == New ? j : nfiles));
++ }
++
++ long maildir_ping (MAILSTREAM *stream)
++ {
++ maildir_parse_folder(stream, 0);
++ return stream && LOCAL ? T : NIL;
++ }
++
++ int maildir_select (struct direct *name)
++ {
++ int rv = NIL, val;
++ val = name->d_name[0] - '0';
++ switch(val){
++ case 1: case 2: case 3: case 4: case 5:
++ case 6: case 7: case 8: case 9:
++ rv = T;
++ default: break;
++ }
++ return rv;
++ }
++
++ /*
++ * Unfortunately, there is no way to sort by arrival in this driver, this
++ * means that opening a folder in this driver using the scandir function
++ * will always make this driver slower than any driver that has a natural
++ * way of sorting by arrival (like a flat file format, "mbox", "mbx", etc).
++ */
++
++ int maildir_namesort (const void *d1,const void *d2)
++ {
++ const struct direct **e1, **e2;
++
++ e1 = (const struct direct **)d1;
++ e2 = (const struct direct **)d2;
++
++ return comp_maildir_file((char*)(*e1)->d_name, (char *)(*e2)->d_name);
++ }
++
++ /* Maildir close */
++
++ void maildir_close (MAILSTREAM *stream, long options)
++ {
++ MESSAGECACHE *elt;
++ unsigned long i;
++ int silent = stream ? stream->silent : 0;
++ mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL);
++
++ if (!stream) return;
++
++ for (i = 1; i <= stream->nmsgs; i++)
++ if ((elt = (MESSAGECACHE *) (*mc) (stream,i,CH_ELT)) && elt->maildirp)
++ maildir_free_file ((void **) &(elt->maildirp));
++ stream->silent = T;
++ if (options & CL_EXPUNGE) maildir_expunge (stream);
++ maildir_abort(stream);
++ stream->silent = silent;
++ }
++
++ void maildir_check (MAILSTREAM *stream)
++ {
++ if (maildir_ping (stream)) mm_log ("Check completed",(long) NIL);
++ }
++
++ long maildir_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs, long flags)
++ {
++ char tmp[MAILTMPLEN+1];
++ unsigned long i;
++ MESSAGECACHE *elt;
++ char *s;
++ /* UID call "impossible" */
++ if (flags & FT_UID || !LOCAL) return NIL;
++ elt = mail_elt (stream,msgno);
++ sprintf (tmp,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ if (LOCAL->fd < 0) /* if file closed ? */
++ LOCAL->fd = open(tmp,O_RDONLY,NIL);
++
++ if (LOCAL->fd < 0 && (errno == EACCES || errno == ENOENT)){
++ INIT (bs, mail_string, "", 0);
++ elt->rfc822_size = 0L;
++ return NIL;
++ }
++
++ if (!(flags & FT_PEEK) && !elt->seen) { /* mark as seen */
++ elt->seen = T;
++ maildir_flagmsg (stream,elt); /* Change flags physically */
++ if (LOCAL->dirty == 0)
++ MM_FLAGS(stream, elt->msgno);
++ }
++ s = maildir_text_work(stream, elt, &i, flags);
++ INIT (bs, mail_string, s, i);
++ return T;
++ }
++
++ char *maildir_text_work (MAILSTREAM *stream,MESSAGECACHE *elt,
++ unsigned long *length,long flags)
++ {
++ FDDATA d;
++ STRING bs;
++ char *s,*t,*tl,tmp[CHUNK];
++ unsigned long msgno = elt->msgno;
++ static int try = 0;
++
++ if (length)
++ *length = 0L;
++ LOCAL->buf[0] = '\0';
++
++ sprintf (tmp,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ if (LOCAL->fd < 0) /* if file closed ? */
++ LOCAL->fd = open(tmp,O_RDONLY,NIL);
++
++ if (LOCAL->fd < 0){ /* flag change? */
++ if (try < 5){
++ try++;
++ if (maildir_update_elt_maildirp(stream, msgno) > 0)
++ try = 0;
++ return maildir_text_work(stream, mail_elt(stream, msgno),length, flags);
++ }
++ try = 0;
++ return NULL;
++ }
++
++ lseek (LOCAL->fd,elt->private.special.offset +
++ elt->private.msg.text.offset,L_SET);
++
++ if (flags & FT_INTERNAL) { /* initial data OK? */
++ if (elt->private.msg.text.text.size > LOCAL->buflen) {
++ fs_give ((void **) &LOCAL->buf);
++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen =
++ elt->private.msg.text.text.size) + 1);
++ }
++ read (LOCAL->fd,LOCAL->buf,elt->private.msg.text.text.size);
++ LOCAL->buf[*length = elt->private.msg.text.text.size] = '\0';
++ }
++ else {
++ if (elt->rfc822_size > LOCAL->buflen) {
++ fs_give ((void **) &LOCAL->buf);
++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = elt->rfc822_size) + 1);
++ }
++ d.fd = LOCAL->fd; /* yes, set up file descriptor */
++ d.pos = elt->private.special.offset + elt->private.msg.text.offset;
++ d.chunk = tmp; /* initial buffer chunk */
++ d.chunksize = CHUNK;
++ INIT (&bs,fd_string,&d,elt->private.msg.text.text.size);
++ for (s = LOCAL->buf; SIZE (&bs);) switch (CHR (&bs)) {
++ case '\r': /* carriage return seen */
++ *s++ = SNX (&bs); /* copy it and any succeeding LF */
++ if (SIZE (&bs) && (CHR (&bs) == '\n')) *s++ = SNX (&bs);
++ break;
++ case '\n':
++ *s++ = '\r'; /* insert a CR */
++ default:
++ *s++ = SNX (&bs); /* copy characters */
++ }
++ *s = '\0'; /* tie off buffer */
++ *length = s - (char *) LOCAL->buf; /* calculate length */
++ }
++ close(LOCAL->fd); LOCAL->fd = -1;
++ return LOCAL->buf;
++ }
++
++ /* maildir parse, fill the elt structure... well not all of it... */
++ unsigned long maildir_parse_message(MAILSTREAM *stream, unsigned long msgno,
++ DirNamesType dirtype)
++ {
++ char *b, *s, c;
++ char tmp[MAILTMPLEN+1];
++ unsigned long i, len;
++ int offset = 0, d, f, r, se, dt;
++ MESSAGECACHE *elt;
++
++ elt = mail_elt (stream,msgno);
++ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), dirtype);
++ if (LOCAL->fd < 0) /* if file closed ? */
++ LOCAL->fd = open(tmp,O_RDONLY,NIL);
++
++ if (LOCAL->fd >= 0){
++ if (elt->day == 0)
++ maildir_get_date(stream, msgno, dirtype);
++ if (LOCAL->fd >= 0){
++ s = (char *) fs_get (MDSIZE(elt) + 1);
++ read (LOCAL->fd,s,MDSIZE(elt));
++ s[MDSIZE(elt)] = '\0';
++ for (i = 0, b = s; *b && !(i && (*b == '\n')); i = (*b++ == '\n'));
++ len = (*b ? ++b : b) - s;
++ elt->private.msg.header.text.size =
++ elt->private.msg.text.offset = len;
++ elt->private.msg.text.text.size = MDSIZE(elt) - len;
++ for (i = 0, b = s, c = *b; b && c &&
++ ((c < '\016') && (((c == '\012') && ++i) ||
++ ((c == '\015') && (*++b == '\012') && (i +=2)))
++ || c); i++, c= *++b);
++ elt->rfc822_size = i;
++ fs_give ((void **) &s);
++ close(LOCAL->fd); LOCAL->fd = -1;
++ }
++ }
++ maildir_getflag(MDFILE(elt), &d, &f, &r ,&se, &dt);
++ elt->draft = d; elt->flagged = f; elt->answered = r; elt->seen = se;
++ elt->deleted = dt; elt->valid = T;
++ return elt->rfc822_size;
++ }
++
++ int
++ maildir_update_elt_maildirp(MAILSTREAM *stream, unsigned long msgno)
++ {
++ char tmp[MAILTMPLEN+1];
++ struct direct **names = NIL;
++ unsigned long i, nfiles, pos;
++ int d = 0, f = 0 , r = 0, s = 0, t = 0, in_list, scan_err;
++ MESSAGECACHE *elt;
++
++ MDFLD(tmp, LOCAL->dir, Cur);
++
++ maildir_scandir (tmp, &names, &nfiles, &scan_err);
++
++ elt = mail_elt (stream,msgno);
++
++ in_list = nfiles > 0L
++ ? maildir_message_in_list(MDFILE(elt), names, 0L,
++ nfiles - 1L, &pos)
++ : NIL;
++
++ if (in_list && pos >= 0L && pos < nfiles
++ && !strcmp(MDFILE(elt), names[pos]->d_name)){
++ in_list = NIL;
++ maildir_abort(stream);
++ }
++
++ if (in_list && pos >= 0L && pos < nfiles){
++ maildir_free_file_only((void **)&elt->maildirp);
++ MDFILE(elt) = cpystr(names[pos]->d_name);
++ maildir_getflag(MDFILE(elt), &d, &f, &r ,&s, &t);
++ if (elt->draft != d || elt->flagged != f ||
++ elt->answered != r || elt->seen != s || elt->deleted != t){
++ elt->draft = d; elt->flagged = f; elt->answered = r;
++ elt->seen = s; elt->deleted = t;
++ MM_FLAGS(stream, msgno);
++ }
++ }
++ for (i = 0L; i < nfiles; i++)
++ fs_give((void **) &names[i]);
++ if (names)
++ fs_give((void **) &names);
++ return in_list ? 1 : -1;
++ }
++
++ /* Maildir fetch message header */
++
++ char *maildir_header (MAILSTREAM *stream,unsigned long msgno,
++ unsigned long *length, long flags)
++ {
++ char tmp[MAILTMPLEN+1], *s;
++ MESSAGECACHE *elt;
++ static int try = 0;
++ unsigned long hdrlen;
++
++ if (length)
++ *length = 0;
++ if (flags & FT_UID || !LOCAL) return ""; /* UID call "impossible" */
++ elt = mail_elt (stream,msgno);
++ if(elt->private.msg.header.text.size == 0)
++ maildir_parse_message(stream, msgno, Cur);
++
++
++ sprintf (tmp,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ if (LOCAL->fd < 0)
++ LOCAL->fd = open (tmp,O_RDONLY,NIL);
++
++ if (LOCAL->fd < 0 && errno == EACCES){
++ mm_log ("Message exists but can not be read. Envelope and body lost!",ERROR);
++ return NULL;
++ }
++
++ if (LOCAL->fd < 0){ /* flag change? */
++ if (try < 5){
++ try++;
++ if (maildir_update_elt_maildirp(stream, msgno) > 0)
++ try = 0;
++ return maildir_header(stream, msgno, length, flags);
++ }
++ try = 0;
++ return NULL;
++ }
++
++ if ((flags & FT_INTERNAL) &&
++ (elt->private.msg.header.text.size > LOCAL->buflen)){
++ fs_give ((void **) &LOCAL->buf);
++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen =
++ elt->private.msg.header.text.size) + 1);
++ }
++ else
++ s = (char *) fs_get(elt->private.msg.header.text.size+1);
++ if (LOCAL->fd >= 0){
++ read (LOCAL->fd, flags & FT_INTERNAL ? (void *)LOCAL->buf : (void *)s,
++ elt->private.msg.header.text.size);
++ if (flags & FT_INTERNAL)
++ LOCAL->buf[*length = elt->private.msg.header.text.size] = '\0';
++ else{
++ s[*length = elt->private.msg.header.text.size] = '\0';
++ *length = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen,s,
++ elt->private.msg.header.text.size);
++ fs_give ((void **) &s);
++ }
++ }
++ elt->private.msg.text.offset = elt->private.msg.header.text.size;
++ elt->private.msg.text.text.size = MDSIZE(elt) - elt->private.msg.text.offset;
++ if(s)
++ fs_give((void **)&s);
++ close(LOCAL->fd); LOCAL->fd = -1;
++ return LOCAL->buf;
++
++
++
++ return LOCAL->buf;
++ }
++
++ /* Maildir find list of subscribed mailboxes
++ * Accepts: mail stream
++ * pattern to search
++ */
++
++ void maildir_list (MAILSTREAM *stream,char *ref, char *pat)
++ {
++ char *s,test[MAILTMPLEN+1],file[MAILTMPLEN+1];
++ long i = 0;
++
++ if (!pat || !*pat) {
++ if (maildir_canonicalize (test,ref,"*")) {
++ if (maildir_valid_name(test)){ /* there is a #md/ leading here */
++ for (i = 3; test[i] && test[i] != '/'; i++);
++ if (s = strchr (test+i+1,'/')) *++s = '\0';
++ else test[0] = '\0';
++ mm_list (stream,'/',test, LATT_NOSELECT);
++ }
++ }
++ }
++ /* get canonical form of name */
++ else if (maildir_canonicalize (test,ref,pat)) {
++ if (test[3] == '/') { /* looking down levels? */
++ /* yes, found any wildcards? */
++ if (s = strpbrk (test,"%*")) {
++ /* yes, copy name up to that point */
++ strncpy (file,test+4,i = s - (test+4));
++ file[i] = '\0'; /* tie off */
++ }
++ else strcpy (file,test+4);/* use just that name then */
++ /* find directory name */
++ if (s = strrchr (file,'/')) {
++ *s = '\0'; /* found, tie off at that point */
++ s = file;
++ }
++ /* do the work */
++ maildir_list_work (stream,s,test,0);
++ }
++ /* always an INBOX */
++ if (!compare_cstring (test,"#MD/INBOX"))
++ mm_list (stream,NIL,"#MD/INBOX",LATT_NOINFERIORS);
++ }
++ }
++
++ /* For those that want to hide things, we give them a chance to do so */
++ void *maildir_parameters (long function,void *value)
++ {
++ switch ((int) function) {
++ case GET_MDINBOX:
++ value = env_parameters (function,NIL);
++ break;
++ default:
++ value = NIL;
++ break;
++ }
++ return value;
++ }
++
++ long maildir_create_work(char *mailbox)
++ {
++ char *s, c, err[MAILTMPLEN+1], tmp[MAILTMPLEN+1];
++ int fnlen, i, create_dir = 0;
++ struct stat sbuf;
++
++ if (mailbox[strlen(mailbox) - 1] == '/'){
++ create_dir++;
++ mailbox[strlen(mailbox) - 1] = '\0';
++ }
++
++ fnlen = strlen(mailbox);
++
++ if (s = strrchr(mailbox,'/')){
++ c = *++s;
++ *s = '\0';
++
++ if ((stat(mailbox,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) &&
++ !maildir_create_work (mailbox))
++ return NIL;
++ *s = c;
++ }
++ mailbox[fnlen] = '\0';
++
++ if (mkdir (mailbox,0700) && errno != EEXIST)
++ return NIL;
++
++ if (create_dir)
++ mailbox[fnlen] = '/';
++
++ if (!create_dir){
++ for (i = Cur; i != EndDir; i++){
++ MDFLD(tmp, mailbox, i);
++
++ if (mkdir(tmp, 0700)){ /* try to make new dir */
++ sprintf (err, "Can't create %s: %s", tmp, strerror(errno));
++ mm_log (err,ERROR);
++ return NIL;
++ }
++ }
++ }
++ else{
++ FILE *fp = NULL;
++ sprintf(tmp,"%s%s", mailbox, MDDIR);
++ if ((fp = fopen(tmp,"w")) == NULL){
++ sprintf (err,"Problem creating %s: %s", tmp, strerror(errno));
++ mm_log (err,ERROR);
++ return NIL;
++ }
++ fclose(fp);
++ }
++ return T; /* return success */
++ }
++
++ long maildir_create (MAILSTREAM *stream,char *mailbox)
++ {
++ char tmp[MAILTMPLEN+1], err[MAILTMPLEN+1];
++ long rv;
++ int create_dir;
++
++ create_dir = mailbox ? (mailbox[strlen(mailbox) - 1] == '/') : 0;
++ maildir_file_path(mailbox, tmp);
++ rv = maildir_create_work(tmp);
++ if (rv == 0L){
++ sprintf (err,"Can't create %s %s: %s %s",
++ create_dir ? "directory" : "mailbox",
++ mailbox, tmp, strerror (errno));
++ mm_log (err,ERROR);
++ }
++ return rv;
++ }
++
++ #define MAXTRY 10000
++ void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt)
++ {
++ char oldfile[MAILTMPLEN+1],newfile[MAILTMPLEN+1],fn[MAILTMPLEN+1];
++ char tmp[MAILTMPLEN+1];
++ char *s;
++ int ren, try = 0;
++
++ LOCAL->dirty = 0;
++ if (elt->valid){
++ for (try = 1; try > 0 && try < MAXTRY; try++){
++ /* build the new filename */
++ sprintf (oldfile,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ fn[0] = '\0';
++ if ((ren = maildir_message_exists(stream, MDFILE(elt), fn)) == 0){
++ errno = ENOENT;
++ try = MAXTRY;
++ }
++ if (*fn) /* new oldfile! */
++ sprintf (oldfile,"%s/%s",LOCAL->curdir,fn);
++ if ((s = strchr (MDFILE(elt), FLAGSEP))) *s = '\0';
++ sprintf (fn,"%s%s%s%s%s%s%s", MDFILE(elt), MDSEP(2),
++ MDFLAG(Draft, elt->draft), MDFLAG(Flagged, elt->flagged),
++ MDFLAG(Replied, elt->answered), MDFLAG(Seen, elt->seen),
++ MDFLAG(Trashed, elt->deleted));
++ sprintf (newfile,"%s/%s",LOCAL->curdir,fn);
++ if (ren != 0 && rename (oldfile,newfile) >= 0){
++ char tmp[MAILTMPLEN+1];
++ try = -1;
++ }
++ }
++
++ if (try > 0){
++ sprintf(oldfile,"Unable to write flags to disk: %s",strerror (errno));
++ mm_log(oldfile,ERROR);
++ LOCAL->dirty = 1;
++ return;
++ }
++ maildir_free_file_only ((void **) &elt->maildirp);
++ MDFILE(elt) = cpystr (fn);
++ }
++ }
++
++ void maildir_expunge (MAILSTREAM *stream)
++ {
++ MESSAGECACHE *elt;
++ unsigned long i;
++ unsigned long n = 0;
++ unsigned long nmsgs = stream->nmsgs;
++ unsigned long recent = stream->recent;
++ char tmp[MAILTMPLEN+1];
++
++ mm_critical (stream); /* go critical */
++ for (i = 1; i <= stream->nmsgs;)
++ if ((elt = mail_elt (stream,i))->deleted){
++ sprintf (tmp,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ if (unlink (tmp)) {/* try to delete the message */
++ sprintf (tmp,"Expunge of message %ld failed, aborted: %s",i,
++ strerror (errno));
++ if (!stream->silent)
++ mm_log (tmp,WARN);
++ break;
++ }
++ /* free the cached filename */
++ if (elt->maildirp)
++ maildir_free_file ((void **) &elt->maildirp);
++
++ if (elt->recent) --recent;/* if recent, note one less recent message */
++ mail_expunged (stream,i); /* notify upper levels */
++ n++; /* count up one more expunged message */
++ }
++ else i++;
++ if (n) { /* output the news if any expunged */
++ sprintf (tmp,"Expunged %ld messages",n);
++ if (!stream->silent)
++ mm_log (tmp,(long) NIL);
++ }
++ else
++ if (!stream->silent)
++ mm_log ("No messages deleted, so no update needed",(long) NIL);
++ mm_nocritical (stream); /* release critical */
++ /* notify upper level of new mailbox size */
++ mail_exists (stream,stream->nmsgs);
++ mail_recent (stream,recent);
++ }
++
++ long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
++ {
++ STRING st;
++ MESSAGECACHE *elt;
++ unsigned long len;
++ int fd;
++ long i, length;
++ char tmp[MAILTMPLEN+1], flags[MAILTMPLEN+1], path[MAILTMPLEN+1], *s, *b;
++ /* copy the messages */
++ if ((options & CP_UID) ? mail_uid_sequence (stream, sequence) :
++ mail_sequence (stream,sequence))
++ for (i = 1; i <= stream->nmsgs; i++)
++ if ((elt = mail_elt (stream,i))->sequence){
++ sprintf (path,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ if ((fd = open (path,O_RDONLY,NIL)) < 0) return NIL;
++ s = (char *) fs_get(MDSIZE(elt) + 1);
++ read (fd,s,MDSIZE(elt));
++ s[MDSIZE(elt)] = '\0';
++ close (fd);
++ len = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen, s, MDSIZE(elt));
++ INIT (&st,mail_string, LOCAL->buf, len);
++ fs_give ((void **)&s);
++
++ flags[0] = flags[1] = '\0';
++ if (elt->seen) strcat (flags," \\Seen");
++ if (elt->draft) strcat (flags," \\Draft");
++ if (elt->deleted) strcat (flags," \\Deleted");
++ if (elt->flagged) strcat (flags," \\Flagged");
++ if (elt->answered) strcat (flags," \\Answered");
++ flags[0] = '('; /* open list */
++ strcat (flags,")"); /* close list */
++ mail_date (tmp,elt); /* generate internal date */
++ if (!mail_append_full (NIL,mailbox,flags,tmp,&st))
++ return NIL;
++ if (options & CP_MOVE) elt->deleted = T;
++ }
++ return T; /* return success */
++ }
++
++ long maildir_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
++ {
++ int fd;
++ STRING *message;
++ char c,*s, *flags, *date;
++ char tmp[MAILTMPLEN+1],file[MAILTMPLEN+1],path1[MAILTMPLEN+1],path2[MAILTMPLEN+1];
++ MESSAGECACHE elt;
++ long i;
++ long size = 0;
++ long ret = LONGT;
++ unsigned long uf;
++ long f;
++ static unsigned int transact = 0;
++
++ if (!maildir_valid(mailbox)) {
++ sprintf (tmp,"Not a valid Maildir mailbox: %s",mailbox);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ if (!*mdlocaldomain)
++ md_domain_name(); /* get domain name for maildir files in mdlocaldomain now! */
++
++ if (!(*af) (stream,data,&flags,&date,&message)) return NIL;
++
++ mm_critical (stream); /* go critical */
++ do {
++ if (!SIZE (message)) { /* guard against zero-length */
++ mm_log ("Append of zero-length message",ERROR);
++ ret = NIL;
++ break;
++ }
++ if (date) { /* want to preserve date? */
++ /* yes, parse date into an elt */
++ if (!mail_parse_date (&elt,date)) {
++ sprintf (tmp,"Bad date in append: %.80s",date);
++ mm_log (tmp,ERROR);
++ ret = NIL;
++ break;
++ }
++ }
++ f = mail_parse_flags (stream,flags,&uf);
++ /* build file name we will use */
++ sprintf (file,"%u.%d_%09u.%s%s%s%s%s%s",
++ time (0),getpid (),transact++,mdlocaldomain, f ? MDSEP(2) : "",
++ MDFLAG(Draft, f&fDRAFT), MDFLAG(Flagged, f&fFLAGGED),
++ MDFLAG(Replied, f&fANSWERED), MDFLAG(Seen, f&fSEEN));
++ /* build tmp file name */
++ if (maildir_file_path(mailbox, tmp))
++ MSGPATH(path1, tmp, file, Tmp);
++
++ if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) {
++ sprintf (tmp,"Can't open append mailbox: %s",strerror (errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ for (size = 0,i = SIZE (message),s = (char *) fs_get (i + 1); i; --i)
++ if ((c = SNX (message)) != '\015') s[size++] = c;
++ if ((write (fd,s,size) < 0) || fsync (fd)) {
++ unlink (path1); /* delete message */
++ sprintf (tmp,"Message append failed: %s",strerror (errno));
++ mm_log (tmp,ERROR);
++ ret = NIL;
++ }
++ fs_give ((void **) &s); /* flush the buffer */
++ close (fd); /* close the file */
++ /* build final filename to use */
++ if (maildir_file_path(mailbox, tmp))
++ MSGPATH(path2, tmp, file, New);
++ if (link (path1,path2) < 0) {
++ sprintf (tmp,"Message append failed: %s",strerror (errno));
++ mm_log (tmp,ERROR);
++ ret = NIL;
++ }
++ unlink (path1);
++
++ if (ret)
++ if (!(*af) (stream,data,&flags,&date,&message)) ret = NIL;
++
++ } while (ret && message); /* write the data */
++
++ mm_nocritical (stream); /* release critical */
++ return ret;
++ }
++
++ long maildir_delete (MAILSTREAM *stream,char *mailbox)
++ {
++ DIR *dirp;
++ struct direct *d;
++ int i, remove_dir = 0, mddir = 0, rv;
++ char tmp[MAILTMPLEN+1],tmp2[MAILTMPLEN+1];
++ struct stat sbuf;
++ char *mdpath = mail_parameters(NIL,GET_MDINBOX,NIL);
++
++ if (mailbox[strlen(mailbox) - 1] == '/'){
++ remove_dir++;
++ mailbox[strlen(mailbox) -1] = '\0';
++ }
++
++ if (!maildir_valid(mailbox)){
++ sprintf(tmp,"%s/%s/", myhomedir(), *(mdfpath+4) ? mdfpath+4
++ : (mdpath ? mdpath : "Maildir"));
++ if (stat(tmp, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode))
++ return NIL;
++ }
++
++ maildir_close(stream,0); /* even if stream was NULL */
++
++ if (remove_dir && !maildir_dir_is_empty(mailbox)){
++ sprintf(tmp,"Can not remove directory %s/: directory not empty", mailbox);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ maildir_file_path(mailbox, tmp2);
++
++ if (remove_dir){
++ sprintf(tmp,"%s/%s", tmp2, MDDIR);
++ if ((rv = stat (tmp,&sbuf)) == 0 && S_ISREG(sbuf.st_mode))
++ rv = unlink(tmp);
++ else if (errno == ENOENT)
++ rv = 0;
++ if (rv != 0){
++ sprintf(tmp,"Can not remove %s/%s: %s", tmp2, MDDIR, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ if (!maildir_valid(mailbox) && rmdir(tmp2) != 0){
++ sprintf(tmp,"Can not remove %s/: %s", tmp2, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ return T;
++ }
++ /* else remove just the folder. Remove all hidden files, except MDDIR */
++ for (i = Cur; i != EndDir; i++){
++ maildir_file_path(mailbox, tmp);
++ MDFLD(tmp2, tmp, i);
++
++ if (!(dirp = opendir (tmp2))){
++ sprintf(tmp,"Can not read %s/: %s", tmp2, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ while (d = readdir(dirp)){
++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")){
++ sprintf(tmp,"%s/%s", tmp2, d->d_name);
++ if (unlink(tmp) != 0){
++ sprintf(tmp,"Can not remove %s: %s", tmp2, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ }
++ }
++ closedir(dirp);
++ if (rmdir(tmp2) != 0){
++ sprintf(tmp,"Can not remove %s: %s", tmp2, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ }
++ /*
++ * ok we have removed all subdirectories of the folder mailbox, Remove the
++ * hidden files.
++ */
++
++ maildir_file_path(mailbox, tmp2);
++ if (!(dirp = opendir (tmp2))){
++ sprintf(tmp,"Can not read %s/: %s", tmp2, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ while (d = readdir(dirp)){
++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")
++ && strcmp(d->d_name, MDDIR)){
++ sprintf(tmp,"%s/%s", tmp2, d->d_name);
++ if (unlink(tmp) != 0){
++ sprintf(tmp,"Can not remove %s: %s", tmp2, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ }
++ else if (!strcmp(d->d_name, MDDIR)) mddir++;
++ }
++ closedir(dirp);
++ if (maildir_dir_is_empty(mailbox) && mddir == 0 && rmdir(tmp2) < 0){
++ sprintf(tmp,"Can not remove folder %s: %s", mailbox, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ return T;
++ }
++
++ long maildir_rename (MAILSTREAM *stream,char *old,char *new)
++ {
++ char tmp[MAILTMPLEN+1],tmpnew[MAILTMPLEN+1];
++ char *maildirpath = mail_parameters(NIL, GET_MDINBOX, NIL);
++
++ if (!maildir_valid(old)){
++ sprintf (tmp,"Can't rename mailbox %s: folder not in maildir format",old);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ sprintf(tmp,"%s/%s/", myhomedir(), *(mdfpath+4) ? mdfpath+4 :
++ maildirpath ? maildirpath : "Maildir");
++
++ if (!maildir_valid_name(new) && new[0] == '#'){
++ sprintf (tmp,"Can't rename mailbox %s: folder not in maildir format",new);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ sprintf(tmpnew,"%s/%s/", myhomedir(), *(mdfpath+4) ? mdfpath+4 :
++ maildirpath ? maildirpath : "Maildir");
++
++ /* new mailbox name must not exist */
++ if (access(tmpnew,F_OK) == 0) {
++ sprintf (tmp,"Can't rename to mailbox %s: destination already exists",new);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ /* try to rename the directory */
++ if (rename (tmp,tmpnew)) {
++ sprintf (tmp,"Can't rename mailbox %s to %s: %s",old,new,strerror (errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ return T; /* return success */
++ }
++
++ long maildir_sub (MAILSTREAM *stream,char *mailbox)
++ {
++ return sm_subscribe (mailbox);
++ }
++
++ long maildir_unsub (MAILSTREAM *stream,char *mailbox)
++ {
++ return sm_unsubscribe (mailbox);
++ }
++
++ void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat)
++ {
++ void *sdb = NIL;
++ char *s, test[MAILTMPLEN+1];
++ /* get canonical form of name */
++ if (maildir_canonicalize (test,ref,pat) && (s = sm_read (&sdb))) {
++ do if (pmatch_full (s,test,'/')) mm_lsub (stream,'/',s,NIL);
++ while (s = sm_read (&sdb)); /* until no more subscriptions */
++ }
++ }
++
++ long maildir_canonicalize (char *pattern,char *ref,char *pat)
++ {
++ if (ref && *ref) { /* have a reference */
++ strcpy (pattern,ref); /* copy reference to pattern */
++ /* # overrides mailbox field in reference */
++ if (*pat == '#') strcpy (pattern,pat);
++ /* pattern starts, reference ends, with / */
++ else if ((*pat == '/') && (pattern[strlen (pattern) - 1] == '/'))
++ strcat (pattern,pat + 1); /* append, omitting one of the period */
++
++ else strcat (pattern,pat); /* anything else is just appended */
++ }
++ else strcpy (pattern,pat); /* just have basic name */
++ return (maildir_valid_name(pattern));
++ }
++
++ void maildir_list_work (MAILSTREAM *stream,char *dir,char *pat,long level)
++ {
++ DIR *dp;
++ struct direct *d;
++ struct stat sbuf;
++ char *cp,*np, curdir[MAILTMPLEN+1],name[MAILTMPLEN+1], tmp[MAILTMPLEN+1];
++ int i;
++ char *maildirpath = mail_parameters(NIL, GET_MDINBOX, NIL);
++
++ sprintf(curdir,"%s/%s/", myhomedir(), dir ? dir :
++ (maildirpath ? maildirpath : "Maildir"));
++ if (dp = opendir (curdir)){
++ if (dir) sprintf (name,"#md/%s/",dir);
++ else strcpy (name,"#md/");
++
++ if (level == 0 && name && pmatch_full (name, pat, '/'))
++ mm_list (stream,'/', name, LATT_NOSELECT);
++
++ while (d = readdir (dp))
++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")
++ && strcmp(d->d_name, MDNAME(Cur))
++ && strcmp(d->d_name, MDNAME(Tmp))
++ && strcmp(d->d_name, MDNAME(New))){
++
++ if (dir) sprintf (tmp,"%s%s", name,d->d_name);
++ else strcpy(tmp, d->d_name);
++
++ if (pmatch_full (tmp,pat,'/')){
++ sprintf(tmp,"%s/%s/%s", myhomedir(), dir ? dir :
++ (maildirpath ? maildirpath : "Maildir"), d->d_name);
++ if (stat (tmp,&sbuf) == 0
++ && ((sbuf.st_mode & S_IFMT) == S_IFDIR)){
++ if (dir) sprintf (tmp,"%s%s", name,d->d_name);
++ else strcpy(tmp, d->d_name);
++ i = maildir_valid(tmp) ? LATT_NOINFERIORS : LATT_NOSELECT;
++ if (i == LATT_NOINFERIORS &&
++ maildir_contains_folder(dir, d->d_name))
++ i = LATT_HASCHILDREN;
++ i += maildir_any_new_msgs(tmp) ? LATT_MARKED : LATT_UNMARKED;
++ mm_list (stream,'/',tmp, i);
++ strcat (tmp, "/");
++ if (dmatch (tmp,pat,'/') &&
++ (level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL))){
++ sprintf(tmp,"%s/%s",dir,d->d_name);
++ maildir_list_work (stream,tmp,pat,level+1);
++ }
++ }
++ }
++ }
++ }
++ closedir (dp);
++ }
++
++ int
++ same_maildir_file(char *name1, char *name2)
++ {
++ char tmp1[MAILTMPLEN+1], tmp2[MAILTMPLEN+1];
++ char *s;
++
++ strcpy(tmp1, name1 ? name1 : "");
++ strcpy(tmp2, name2 ? name2 : "");
++ if (s = strchr(tmp1, FLAGSEP))
++ *s = '\0';
++ if (s = strchr(tmp1, SIZESEP))
++ *s = '\0';
++ if (s = strchr(tmp2, FLAGSEP))
++ *s = '\0';
++ if (s = strchr(tmp2, SIZESEP))
++ *s = '\0';
++
++ return !strcmp(tmp1, tmp2);
++ }
++
++
++ int comp_maildir_file(char *name1, char *name2)
++ {
++ unsigned long t1, t2;
++ int i;
++
++ if (!(name1 && *name1))
++ return name2 && *name2 ? (*name2 == FLAGSEP ? 0 : -1) : 0;
++
++ if (!(name2 && *name2))
++ return name1 && *name1 ? (*name1 == FLAGSEP ? 0 : 1) : 0;
++
++ if(!strcmp(name1,name2))
++ return 0;
++
++ t1 = strtoul(name1, NULL, 10);
++ t2 = strtoul(name2, NULL, 10);
++
++ if (t1 < t2)
++ return -1;
++
++ if (t1 > t2)
++ return 1;
++
++ i = strchr(name1,'.') - name1 + 1;
++ return (strcmp (name1 + i, name2 + i));
++ }
++
++ void
++ maildir_getflag(char *name, int *d, int *f, int *r ,int *s, int *t)
++ {
++ char tmp[MAILTMPLEN+1], *b;
++ int offset = 0;
++
++ if(d && f && r && s && t)
++ *d = *f = *r = *s = *t = 0;
++ else
++ return; /* can not call this function with null arguments */
++
++ strcpy(tmp,name);
++ while (b = strchr(tmp+offset, FLAGSEP)){
++ char flag,last;
++ int i,k;
++ if (!++b) break;
++ switch (*b){
++ case '1':
++ case '2':
++ case '3': flag = *b; b += 2;
++ for (k = 0; b[k] && b[k] != FLAGSEP && b[k] != ','; k++);
++ last = b[k];
++ b[k] = '\0';
++ if (flag == '2' || flag == '3'){
++ *d = strchr (b, MDFLAGC(Draft)) ? T : NIL;
++ *f = strchr (b, MDFLAGC(Flagged)) ? T : NIL;
++ *r = strchr (b, MDFLAGC(Replied)) ? T : NIL;
++ *s = strchr (b, MDFLAGC(Seen)) ? T : NIL;
++ *t = strchr (b, MDFLAGC(Trashed)) ? T : NIL;
++ }
++ b[k] = last;
++ b += k;
++ for (; tmp[offset] && tmp[offset] != FLAGSEP; offset++);
++ offset++;
++ break;
++ default: break; /* Should we crash?... Nahhh */
++ }
++ }
++ }
++
++ int
++ maildir_message_in_list(char *msgname, struct direct **names,
++ unsigned long bottom, unsigned long top, unsigned long *pos)
++ {
++ unsigned long middle = (bottom + top)/2;
++ int test;
++
++ if (!msgname)
++ return NIL;
++
++ if (pos) *pos = middle;
++
++ if (same_maildir_file(msgname, names[middle]->d_name))
++ return T;
++
++ if (middle == bottom){ /* 0 <= 0 < 1 */
++ int rv = NIL;
++ if (same_maildir_file(msgname, names[middle]->d_name)){
++ rv = T;
++ if (pos) *pos = middle;
++ }
++ else
++ if (same_maildir_file(msgname, names[top]->d_name)){
++ rv = T;
++ if (pos) *pos = top;
++ }
++ return rv;
++ }
++
++ test = comp_maildir_file(msgname, names[middle]->d_name);
++
++ if (top <= bottom)
++ return test ? NIL : T;
++
++ if (test < 0 ) /* bottom < msgname < middle */
++ return maildir_message_in_list(msgname, names, bottom, middle, pos);
++ else if (test > 0) /* middle < msgname < top */
++ return maildir_message_in_list(msgname, names, middle, top, pos);
++ else return T;
++ }
++
++ void
++ maildir_abort(MAILSTREAM *stream)
++ {
++ if (LOCAL){
++ if (LOCAL->dir) fs_give ((void **) &LOCAL->dir);
++ if (LOCAL->curdir) fs_give ((void **) &LOCAL->curdir);
++ if (LOCAL->buf) fs_give ((void **) &LOCAL->buf);
++ fs_give ((void **) &stream->local);
++ }
++ if (mdfpath) fs_give((void **)&mdfpath);
++ stream->dtb = NIL;
++ }
++
++ int
++ maildir_contains_folder(char *dirname, char *name)
++ {
++ char tmp[MAILTMPLEN+1], tmp2[MAILTMPLEN+1];
++ int rv = 0;
++ DIR *dir;
++ struct direct *d;
++ struct stat sbuf;
++ char *maildirpath = mail_parameters(NIL, GET_MDINBOX, NIL);
++
++ sprintf(tmp2,"%s/%s/%s", myhomedir(), dirname ? dirname
++ : (maildirpath ? maildirpath : "Maildir"), name);
++
++ if (!(dir = opendir (tmp2)))
++ return NIL;
++
++ while (d = readdir(dir)){
++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")
++ && strcmp(d->d_name, MDNAME(Cur))
++ && strcmp(d->d_name, MDNAME(Tmp))
++ && strcmp(d->d_name, MDNAME(New))){
++
++ sprintf(tmp,"%s/%s", tmp2, d->d_name);
++ if (stat (tmp,&sbuf) == 0
++ && ((sbuf.st_mode & S_IFMT) == S_IFDIR ||
++ (S_ISREG(sbuf.st_mode) && !strcmp(d->d_name, MDDIR)))){
++ rv++;
++ break;
++ }
++ }
++ }
++ closedir(dir);
++ return rv;
++ }
++
++ int
++ maildir_dir_is_empty(char *mailbox)
++ {
++ char tmp[MAILTMPLEN+1], tmp2[MAILTMPLEN+1];
++ int rv = 1;
++ DIR *dir;
++ struct direct *d;
++ struct stat sbuf;
++
++ maildir_file_path(mailbox, tmp2);
++
++ if (!(dir = opendir (tmp2)))
++ return rv;
++
++ while (d = readdir(dir)){
++ sprintf(tmp,"%s/%s", tmp2, d->d_name);
++ if (strcmp(d->d_name, ".")
++ && strcmp(d->d_name,"..")
++ && strcmp(d->d_name, MDNAME(Cur))
++ && strcmp(d->d_name, MDNAME(Tmp))
++ && strcmp(d->d_name, MDNAME(New))
++ && strcmp(d->d_name, MDDIR)
++ && strcmp(d->d_name, MDUIDVALIDITY)
++ && !(d->d_name[0] == '.'
++ && stat (tmp,&sbuf) == 0
++ && S_ISREG(sbuf.st_mode))){
++ rv = 0;
++ break;
++ }
++ }
++ closedir(dir);
++ return rv;
++ }
++
++ void
++ maildir_get_file (MAILDIRFILE **mdfile)
++ {
++ MAILDIRFILE *md;
++
++ md = (MAILDIRFILE *) fs_get(sizeof(MAILDIRFILE));
++ memset(md, 0, sizeof(MAILDIRFILE));
++ *mdfile = md;
++ }
++
++ void
++ maildir_free_file (void **mdfile)
++ {
++ MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL;
++
++ if (md){
++ if (md->name) fs_give((void **)&md->name);
++ fs_give((void **)&md);
++ }
++ }
++
++ void
++ maildir_free_file_only (void **mdfile)
++ {
++ MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL;
++
++ if (md && md->name)
++ fs_give((void **)&md->name);
++ }
++
++ int
++ maildir_any_new_msgs(char *mailbox)
++ {
++ char tmp[MAILTMPLEN+1];
++ int rv = NIL;
++ DIR *dir;
++ struct direct *d;
++ struct stat sbuf;
++
++ MDFLD(tmp, mailbox, New);
++
++ if (!(dir = opendir (tmp)))
++ return rv;
++
++ while (d = readdir(dir)){
++ if (d->d_name[0] == '.')
++ continue;
++ rv = T;
++ break;
++ }
++ closedir(dir);
++ return rv;
++ }
++
++
++ void
++ maildir_get_date(MAILSTREAM *stream, unsigned long msgno, DirNamesType dirtype)
++ {
++ MESSAGECACHE *elt;
++ char tmp[MAILTMPLEN+1];
++ struct tm *tm;
++ struct stat sbuf;
++
++ elt = mail_elt (stream,msgno);
++ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), dirtype);
++
++ if(MDSIZE(elt) == (off_t) 0 && stat(tmp, &sbuf) == 0){
++ MDSIZE(elt) = sbuf.st_size;
++ MDMTIME(elt) = sbuf.st_mtime;
++ }
++
++
++ if (MDMTIME(elt) > 0){
++ tm = gmtime (&MDMTIME(elt));
++ elt->day = tm->tm_mday; elt->month = tm->tm_mon + 1;
++ elt->year = tm->tm_year + 1900 - BASEYEAR;
++ elt->hours = tm->tm_hour; elt->minutes = tm->tm_min;
++ elt->seconds = tm->tm_sec;
++ elt->zhours = 0; elt->zminutes = 0;
++ }
++ }
+diff -rc pine4.61/imap/src/osdep/unix/maildir.h pine4.61.maildir/imap/src/osdep/unix/maildir.h
+*** pine4.61/imap/src/osdep/unix/maildir.h Sat Dec 11 15:12:09 2004
+--- pine4.61.maildir/imap/src/osdep/unix/maildir.h Sun Dec 5 20:51:17 2004
+***************
+*** 0 ****
+--- 1,145 ----
++ /*
++ * A few definitions that try to make this module portable to other
++ * platforms (e.g. Cygwin). This module is based on the information from
++ * http://cr.yp.to/proto/maildir.html
++ */
++
++ /* First we deal with the separator character */
++ #ifndef FLAGSEP
++ #define FLAGSEP ':'
++ #endif
++ #define SIZESEP ','
++
++ #define MDUIDVALIDITY ".uidvalidity" /* support for old maildirs */
++ #define MDDIR ".mdir" /* this folder is a directory */
++
++ const char sep1[] = {FLAGSEP, '1', ',', '\0'}; /* experimental semantics*/
++ const char sep2[] = {FLAGSEP, '2', ',', '\0'}; /* Flags Information */
++ const char sep3[] = {FLAGSEP, '3', ',', '\0'}; /* Grrrr.... */
++
++ const char *sep[] = { sep1, sep2, sep3, NULL};
++
++ #define MDSEP(i) sep[((i) - 1)]
++
++ /* Now we deal with flags. Woohoo! */
++ typedef enum {Draft, Flagged, Passed, Replied, Seen, Trashed,
++ EmptyFlag, EndFlags} MdFlagNamesType;
++ const int mdimapflags[] = {Draft, Flagged, Replied, Seen, Trashed, EmptyFlag, EndFlags};
++ const int mdkwdflags[] = {Passed, EmptyFlag, EndFlags};
++
++ /* this array lists the codes for mdflgnms (maildir flag names) above */
++ const char *mdflags[] = { "D", "F", "P", "R", "S", "T", "", NULL};
++ /* and as characters too */
++ const char cmdflags[] = { 'D', 'F', 'P', 'R', 'S', 'T', '0', '\0'};
++
++ /* MDFLAG(Seen, elt->seen) */
++ #define MDFLAG(i,j) mdflags[j ? (i) : EmptyFlag]
++ /* MDFLAGC(Seen) */
++ #define MDFLAGC(i) cmdflags[(i)]
++
++ /* Now we deal with the directory structure */
++ typedef enum {Cur, Tmp, New, EndDir} DirNamesType;
++ char *mdstruct[] = {"cur", "tmp", "new", NULL};
++ #define MDNAME(i) mdstruct[(i)]
++ #define MDFLD(tmp, dir, i) sprintf((tmp),"%s/%s", (dir), mdstruct[(i)])
++ #define MSGPATH(tmp, dir, msg,i) sprintf((tmp),"%s/%s/%s", (dir), mdstruct[(i)],(msg))
++
++ /* Now we deal with messages filenames */
++ char mdlocaldomain[MAILTMPLEN+1] = {'\0'};
++ static char *mdfpath = NULL;
++ #define CHUNK 16384 /* from unix.h */
++ /* In gdb this is the *(struct maildir_local *)stream->local structure */
++
++ typedef struct maildir_local {
++ unsigned int inbox : 1; /* if it is an INBOX or not */
++ unsigned int dirty : 1; /* diskcopy needs updating */
++ int fd; /* fd of open message */
++ char *dir; /* mail directory name */
++ char *curdir; /* mail directory name/cur */
++ unsigned char *buf; /* temporary buffer */
++ char *hdr; /* current header */
++ unsigned long buflen; /* current size of temporary buffer */
++ time_t scantime; /* last time directory scanned */
++ } MAILDIRLOCAL;
++
++ /* Convenient access to local data */
++ #define LOCAL ((MAILDIRLOCAL *) stream->local)
++
++ typedef struct maildir_file_info {
++ char *name; /* name of the file */
++ unsigned long pos; /* place in list where this file is listed */
++ off_t size; /* size in bytes, on disk */
++ time_t atime; /* last access time */
++ time_t mtime; /* last modified time */
++ time_t ctime; /* last changed time */
++ } MAILDIRFILE;
++
++ #define MDFILE(F) (((MAILDIRFILE *)((F)->maildirp))->name)
++ #define MDPOS(F) (((MAILDIRFILE *)((F)->maildirp))->pos)
++ #define MDSIZE(F) (((MAILDIRFILE *)((F)->maildirp))->size)
++ #define MDATIME(F) (((MAILDIRFILE *)((F)->maildirp))->atime)
++ #define MDMTIME(F) (((MAILDIRFILE *)((F)->maildirp))->mtime)
++ #define MDCTIME(F) (((MAILDIRFILE *)((F)->maildirp))->ctime)
++
++ /* Function prototypes */
++
++ DRIVER *maildir_valid (char *name);
++ MAILSTREAM *maildir_open (MAILSTREAM *stream);
++ void maildir_gc (MAILSTREAM *stream,long gcflags);
++ void maildir_close (MAILSTREAM *stream, long options);
++ long maildir_ping (MAILSTREAM *stream);
++ long maildir_ping_core (MAILSTREAM *stream);
++ void maildir_check (MAILSTREAM *stream);
++ long maildir_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);
++ char *maildir_header (MAILSTREAM *stream,unsigned long msgno,
++ unsigned long *length, long flags);
++ void maildir_list (MAILSTREAM *stream,char *ref,char *pat);
++ void *maildir_parameters (long function,void *value);
++ long maildir_create (MAILSTREAM *stream,char *mailbox);
++ void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt); /*check */
++ void maildir_expunge (MAILSTREAM *stream);
++ long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);
++ long maildir_append (MAILSTREAM *stream,char *mailbox, append_t af, void *data);
++ long maildir_delete (MAILSTREAM *stream,char *mailbox);
++ long maildir_rename (MAILSTREAM *stream,char *old,char *new);
++ long maildir_sub (MAILSTREAM *stream,char *mailbox);
++ long maildir_unsub (MAILSTREAM *stream,char *mailbox);
++ void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat);
++
++ /* utility functions */
++ char *maildir_file (char *dst,char *name);
++ int maildir_select (struct direct *name);
++ int maildir_namesort (const void *d1, const void *d2);
++ void maildir_listwork(char *name, MAILSTREAM *stream, char *s2, char *subdir, int flag);
++ long maildir_canonicalize (char *pattern,char *ref,char *pat);
++ void maildir_list_work (MAILSTREAM *stream,char *subdir,char *pat,long level);
++ int maildir_file_path(char *name, char *tmp);
++ int maildir_valid_name (char *name);
++ int maildir_valid_dir (char *name);
++ int maildir_base_name (char *name, char *tmp);
++ int maildir_message_exists(MAILSTREAM *stream,char *name, char *tmp);
++ void maildir_remove_root(char **name);
++ char *maildir_text_work (MAILSTREAM *stream,MESSAGECACHE *elt, unsigned long *length,long flags);
++ unsigned long maildir_parse_message(MAILSTREAM *stream, unsigned long msgno,
++ DirNamesType dirtype);
++ unsigned long maildir_scandir (char *name, struct direct ***flist,
++ unsigned long *nfiles, int *scand);
++ void maildir_parse_folder (MAILSTREAM *stream, int full);
++ void md_domain_name (void);
++ unsigned long maildir_parse_dir(MAILSTREAM *stream, unsigned long nmsgs,
++ DirNamesType dirtype, int full);
++ int same_maildir_file(char *name1, char *name2);
++ int comp_maildir_file(char *name1, char *name2);
++ int maildir_message_in_list(char *msgname, struct direct **names,
++ unsigned long bottom, unsigned long top, unsigned long *pos);
++ void maildir_getflag(char *name, int *d, int *f, int *r ,int *s, int *t);
++ int maildir_update_elt_maildirp(MAILSTREAM *stream, unsigned long msgno);
++ void maildir_abort (MAILSTREAM *stream);
++ int maildir_contains_folder(char *dirname, char *name);
++ int maildir_dir_is_empty(char *mailbox);
++ long maildir_create_work (char *mailbox);
++ void maildir_get_file (MAILDIRFILE **mdfile);
++ void maildir_free_file (void **mdfile);
++ void maildir_free_file_only (void **mdfile);
++ int maildir_any_new_msgs(char *mailbox);
++ void maildir_get_date(MAILSTREAM *stream, unsigned long msgno, DirNamesType dirtype);
+diff -rc pine4.61/imap/src/osdep/unix/os_cyg.h pine4.61.maildir/imap/src/osdep/unix/os_cyg.h
+*** pine4.61/imap/src/osdep/unix/os_cyg.h Mon Apr 19 08:23:48 2004
+--- pine4.61.maildir/imap/src/osdep/unix/os_cyg.h Wed Nov 24 15:15:18 2004
+***************
+*** 39,44 ****
+--- 39,45 ----
+ #define setpgrp setpgid
+
+ #define SYSTEMUID 18 /* Cygwin returns this for SYSTEM */
++ #define FLAGSEP ';'
+ #define geteuid Geteuid
+ uid_t Geteuid (void);
+
+diff -rc pine4.61/pine/folder.c pine4.61.maildir/pine/folder.c
+*** pine4.61/pine/folder.c Mon Jul 12 19:26:16 2004
+--- pine4.61.maildir/pine/folder.c Wed Nov 24 15:15:18 2004
+***************
+*** 5752,5759 ****
+ }
+ else{
+ sprintf(ques_buf, "DELETE \"%.100s\"%s", folder,
+! close_opened ? " (the currently open folder)"
+! : fp->isdir ? " (a directory)" : "");
+
+ if((ret = want_to(ques_buf, 'n', 'x', NO_HELP, WT_NORM)) != 'y'){
+ q_status_message(SM_ORDER,0,3, (ret == 'x') ? "Delete cancelled"
+--- 5752,5760 ----
+ }
+ else{
+ sprintf(ques_buf, "DELETE \"%.100s\"%s", folder,
+! (!fp->isfolder || (fp->isdir && !close_opened))
+! ? " (a directory)"
+! : close_opened ? " (the currently open folder)" : "");
+
+ if((ret = want_to(ques_buf, 'n', 'x', NO_HELP, WT_NORM)) != 'y'){
+ q_status_message(SM_ORDER,0,3, (ret == 'x') ? "Delete cancelled"
+***************
+*** 5787,5793 ****
+ && context_same_stream(context, fp->name, *possible_streamp))
+ del_stream = *possible_streamp;
+
+! if(!fp->isfolder)
+ sprintf(fnamep = fname, "%.*s%c", sizeof(fname)-3, fp->name,
+ context->dir->delim);
+ else
+--- 5788,5794 ----
+ && context_same_stream(context, fp->name, *possible_streamp))
+ del_stream = *possible_streamp;
+
+! if(!fp->isfolder || (fp->isdir && !close_opened))
+ sprintf(fnamep = fname, "%.*s%c", sizeof(fname)-3, fp->name,
+ context->dir->delim);
+ else
+***************
+*** 5803,5810 ****
+ }
+
+ q_status_message2(SM_ORDER, 0, 3, "%.200s \"%.200s\" deleted.",
+! blast_folder ? "Folder" : "Nickname", folder);
+!
+
+ if(context->use & CNTXT_INCMNG){
+ char **new_list, **lp, ***alval;
+--- 5804,5813 ----
+ }
+
+ q_status_message2(SM_ORDER, 0, 3, "%.200s \"%.200s\" deleted.",
+! blast_folder
+! ? (!fp->isfolder || (fp->isdir && !close_opened))
+! ? "Directory" : "Folder"
+! : "Nickname", folder);
+
+ if(context->use & CNTXT_INCMNG){
+ char **new_list, **lp, ***alval;
+diff -rc pine4.61/pine/init.c pine4.61.maildir/pine/init.c
+*** pine4.61/pine/init.c Thu Jul 15 10:37:24 2004
+--- pine4.61.maildir/pine/init.c Wed Nov 24 15:15:18 2004
+***************
+*** 408,413 ****
+--- 408,416 ----
+
+ CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file";
+
++ CONF_TXT_T cf_text_maildir_location[] = "Location relative to your HOME directory of the directory where your INBOX\n# for the maildir format is located. Default value is \"Maildir\". If your\n# inbox is located at \"~/Maildir\" you do not need to change this value.\n# A common value is also \".maildir\"";
++
++
+ /* these are used to report folder directory creation problems */
+ CONF_TXT_T init_md_exists[] = "The \"%s\" subdirectory already exists, but it is not writable by Pine so Pine cannot run. Please correct the permissions and restart Pine.";
+
+***************
+*** 591,596 ****
+--- 594,601 ----
+ cf_text_news_active},
+ {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0,
+ cf_text_news_spooldir},
++ {"maildir-location", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0,
++ cf_text_maildir_location},
+ {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0,
+ cf_text_upload_cmd},
+ {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0,
+***************
+*** 2065,2070 ****
+--- 2070,2079 ----
+ mail_parameters(NULL, SET_NEWSSPOOL,
+ (void *)VAR_NEWS_SPOOL_DIR);
+
++ set_current_val(&vars[V_MAILDIR_LOCATION], TRUE, TRUE);
++ if(VAR_MAILDIR_LOCATION && VAR_MAILDIR_LOCATION[0])
++ mail_parameters(NULL, SET_MDINBOX, (void *)VAR_MAILDIR_LOCATION);
++
+ /* guarantee a save default */
+ set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE);
+ if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0])
+diff -rc pine4.61/pine/other.c pine4.61.maildir/pine/other.c
+*** pine4.61/pine/other.c Fri Jul 2 14:38:16 2004
+--- pine4.61.maildir/pine/other.c Wed Nov 24 15:15:18 2004
+***************
+*** 7464,7469 ****
+--- 7464,7471 ----
+ return(h_config_mimetype_path);
+ case V_NEWSRC_PATH :
+ return(h_config_newsrc_path);
++ case V_MAILDIR_LOCATION :
++ return(h_config_maildir_location);
+ case V_BROWSER :
+ return(h_config_browser);
+ #if defined(DOS) || defined(OS2)
+***************
+*** 12720,12725 ****
+--- 12722,12732 ----
+ (void *)var->current_val.p);
+ }
+ #endif
++ else if(var == &ps->vars[V_MAILDIR_LOCATION]){
++ if(var->current_val.p && var->current_val.p[0])
++ mail_parameters(NULL, SET_MDINBOX,
++ (void *)var->current_val.p);
++ }
+ else if(revert && standard_radio_var(ps, var)){
+
+ cur_rule_value(var, TRUE, FALSE);
+diff -rc pine4.61/pine/pine.c pine4.61.maildir/pine/pine.c
+*** pine4.61/pine/pine.c Wed Jul 14 11:17:13 2004
+--- pine4.61.maildir/pine/pine.c Wed Nov 24 15:15:18 2004
+***************
+*** 552,558 ****
+ rv = 0;
+ if(pine_state->VAR_TCPWRITEWARNTIMEO){
+ if(!SVAR_TCP_WRITEWARN(pine_state, rv, tmp_20k_buf))
+! if(rv == 0 || rv > 4) /* making sure */
+ mail_parameters(NULL, SET_WRITETIMEOUT, (void *)(long)rv);
+ }
+
+--- 552,558 ----
+ rv = 0;
+ if(pine_state->VAR_TCPWRITEWARNTIMEO){
+ if(!SVAR_TCP_WRITEWARN(pine_state, rv, tmp_20k_buf))
+! if(rv == 0 || rv > 4) /* making sure */
+ mail_parameters(NULL, SET_WRITETIMEOUT, (void *)(long)rv);
+ }
+
+diff -rc pine4.61/pine/pine.h pine4.61.maildir/pine/pine.h
+*** pine4.61/pine/pine.h Wed Jul 14 17:25:12 2004
+--- pine4.61.maildir/pine/pine.h Wed Nov 24 15:15:19 2004
+***************
+*** 661,666 ****
+--- 661,667 ----
+ , V_NEWSRC_PATH
+ , V_NEWS_ACTIVE_PATH
+ , V_NEWS_SPOOL_DIR
++ , V_MAILDIR_LOCATION
+ , V_UPLOAD_CMD
+ , V_UPLOAD_CMD_PREFIX
+ , V_DOWNLOAD_CMD
+***************
+*** 951,956 ****
+--- 952,959 ----
+ #define GLO_NEWS_ACTIVE_PATH vars[V_NEWS_ACTIVE_PATH].global_val.p
+ #define VAR_NEWS_SPOOL_DIR vars[V_NEWS_SPOOL_DIR].current_val.p
+ #define GLO_NEWS_SPOOL_DIR vars[V_NEWS_SPOOL_DIR].global_val.p
++ #define VAR_MAILDIR_LOCATION vars[V_MAILDIR_LOCATION].current_val.p
++ #define GLO_MAILDIR_LOCATION vars[V_MAILDIR_LOCATION].global_val.p
+ #define VAR_DISABLE_DRIVERS vars[V_DISABLE_DRIVERS].current_val.l
+ #define VAR_DISABLE_AUTHS vars[V_DISABLE_AUTHS].current_val.l
+ #define VAR_REMOTE_ABOOK_METADATA vars[V_REMOTE_ABOOK_METADATA].current_val.p
+diff -rc pine4.61/pine/pine.hlp pine4.61.maildir/pine/pine.hlp
+*** pine4.61/pine/pine.hlp Thu Jul 15 10:37:22 2004
+--- pine4.61.maildir/pine/pine.hlp Wed Nov 24 15:15:19 2004
+***************
+*** 18750,18755 ****
+--- 18750,18845 ----
+ <End of help on this topic>
+ </BODY>
+ </HTML>
++ ====== h_config_maildir_location ======
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: maildir-location</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: maildir-location</H1>
++
++ <P>
++ This option should be used only if you have a Maildir folder which you
++ want to use as your INBOX. If this is not your case (or don't know what
++ this is), you can safely ignore this option.
++
++ <P>
++ This option overrides the default directory Pine uses to find the location of
++ your INBOX, in case this is in Maildir format. The default value of this
++ option is "Maildir", but in some systems, this directory could have been
++ renamed (e.g. to ".maildir"). If this is your case use this option to change
++ the default.
++
++ <P>
++ The value of this option is prefixed with the "~/" string to determine the
++ full path to your INBOX.
++
++ <P>
++ You should probably <A HREF="h_config_maildir">read</A> a few tips that
++ teach you how to configure your maildir for optimal performance.
++
++ <P><UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL>
++ <P>
++ <End of help on this topic>
++ </BODY>
++ </HTML>
++ ====== h_config_maildir =====
++ <HTML>
++ <HEAD>
++ <TITLE>Maildir Support</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>Maildir Support</H1>
++
++ This version of Pine has been enhanced with Maildir support. This text is
++ intended to be a reference on its support.
++ <P>
++
++ A Maildir folder is a directory that contains three directories called
++ cur, tmp and new. A program that delivers mail (e.g. postfix) will put new
++ mail in the new directory. A program that reads mail will look for for old
++ messages in the cur directory, while it will look for new mail in the new
++ directory.
++ <P>
++
++ In order to use maildir support it is better to set your inbox-path to the
++ value "#md/inbox" (without quotes). This assumes that your mail
++ delivery agent is delivering new mail to ~/Maildir/new. If the directory
++ where new mail is being delivered is not called "Maildir", you can set the
++ name of the subdirectory of home where it is being delivered in the <A
++ HREF="h_config_maildir_location">maildir-location</A> configuration
++ variable. Most of the time you will not have to worry about the
++ maildir-location variable, because it will probably be set by your
++ administrator in the pine.conf configuration file.
++ <P>
++
++ One of the advantages of the Maildir support of this version of Pine is
++ that you do not have to stop using folders in another styles (mbox, mbx,
++ etc.). This is desirable since the usage of a specific mail storage system
++ is a personal decision. Folders in the maildir format that are part of the
++ Mail collection will be recognized without any extra configuration of your
++ part. If your mail/ collection is located under the mail/ directory, then
++ creating a new maildir folder in this collection is done by pressing "A"
++ and entering the string "#driver.md/mail/newfolder". Observe that adding a
++ new folder as "newfolder" may not create such folder in maildir format.
++ <P>
++
++ If you would like to have all folders created in the maildir format by
++ default, you do so by adding a Maildir Collection. In order to convert
++ your current mail/ collection into a maildir collection, edit the
++ collection and change the pah variable from "mail/" to
++ "#md/mail". In a maildir collection folders of any other format
++ are ignored.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ <End of help on this topic>
++ </BODY>
++ </HTML>
+ ====== h_config_literal_sig =====
+ <HTML>
+ <HEAD>
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-ports-bugs
mailing list