changeset 1:28a55bc1110c imapext-2007-1

[mq]: imapext
author yuuji@gentei.org
date Mon, 14 Sep 2009 19:23:11 +0900
parents ada5e610ab86
children fc6002700ecd
files APOPtools/Makefile APOPtools/apopcall.c APOPtools/apoppasswd APOPtools/deapop APOPtools/deapop.gzip APOPtools/index.html APOPtools/pop3-age APOPtools/pop3-record APOPtools/pop3-record.postfix APOPtools/pop3-update APOPtools/qmapmore.html APOPtools/with-tcpserver/0README APOPtools/with-tcpserver/Makefile APOPtools/with-tcpserver/log/run APOPtools/with-tcpserver/pop APOPtools/with-tcpserver/run Makefile README.maildir README.qmailapop src/c-client/auth_log.c src/c-client/auth_md5.c src/c-client/mail.c src/c-client/mail.h src/imapd/imapd.c src/ipopd/ipop3d.c src/osdep/unix/Makefile src/osdep/unix/env_unix.c src/osdep/unix/maildir.c src/osdep/unix/maildir.h src/osdep/unix/tcp_unix.c src/osdep/unix/unix.c
diffstat 31 files changed, 3585 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/Makefile	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,30 @@
+#
+# install script
+#
+PERMSMTPDIR	= /usr/local/etc
+DEAPOPDIR	= /usr/local/sbin
+BINDIR		= /usr/local/bin
+CGIDIR		= /usr/local/apache/cgi-bin
+
+
+all:	apopcall
+
+LDFLAGS	= -lcrypt
+
+apopcall:	apopcall.c
+
+
+install:
+	-@[ -d ${PERMSMTPDIR} ] || mkdir -p ${PERMSMTPDIR}
+	install -c -m 700 pop3-record ${PERMSMTPDIR}
+	csh -c 'ln -f ${PERMSMTPDIR}/pop3-{record,age}'
+	csh -c 'ln -f ${PERMSMTPDIR}/pop3-{record,update}'
+	-@[ -d ${DEAPOPDIR} ] || mkdir -p ${DEAPOPDIR}
+	install -c -m 700 deapop ${DEAPOPDIR}
+	install -c -m 755 apoppasswd ${BINDIR}
+
+install-cgi:	apopcall
+	install -cs -m 4755 -o 0 apopcall ${CGIDIR}/apopcall.cgi
+
+clean:
+	rm apopcall
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/apopcall.c	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,526 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#ifdef SHADOW_PASSWD
+#include <shadow.h>
+#endif
+
+#ifndef APOPPASSWD
+#define APOPPASSWD "/usr/local/bin/apoppasswd"
+#endif
+#ifndef APOPFILEBASE
+#define APOPFILEBASE ".apop"
+#endif
+#ifndef XADDR_DELIM
+#define XADDR_DELIM ('-')
+#endif
+
+char *myname;
+
+int ishexa(int c) {
+    strchr("0123456789ABCDFabcdef", c) ? 1 : 0;
+}
+
+put_form(email, pass, new, new2, suffix, hidden, auth, force)
+     char *email, *pass, *new, *new2, *suffix;
+     int hidden, auth, force;
+     /* auth = 0: old password
+               1: base addresse's mail password
+               2: unix password */
+{
+    char *authtype[] = {"old", "base", "unix"};
+    char *var[] = {"email", "pass", "new", "new2", "auth", ""};
+    char *val[] = {email, pass, new, new2, authtype[auth]};
+    char *prm[] = {"",  /* "ユーザ名", */
+                   auth ? 
+                   ((auth==1)
+                    ? "基本メイルアドレス用パスワード<br>Password for Basic Mail address"
+                    : "UNIXログインパスワード<br>UNIX login Password")
+                   : "古いメイルパスワード<br>Old Mail Password",
+                   "新しいメイルパスワード<br>New Mail Password",
+                   "新パスワードをもう一回(確認)<br>New Mail Password Again",
+		   ""};
+    int h=0, i;
+
+    printf("<form method=POST action\"./%s\">\n", myname);
+    printf(" <table border=1>\n");
+    for (i=0; var[i][0]; i++) {
+        h = hidden || strstr("email,suffix,auth", var[i]);
+	if (prm[i][0]) {
+            printf("<tr><td>%s</td><td>", prm[i]);
+	} else {
+	}
+        printf("<input name=%s %svalue=\"%s\" length=40 maxlength=40>\n",
+               var[i],
+               h ? "type=hidden "
+               : (strstr(prm[i], "パスワード") ? "type=password " : "<br>"),
+               val[i]);
+        if (!strcmp(var[i], "suffix")) {
+            /* ここでは suffix を入れさせない方がいいかも */
+	    /* 表向きのメイルアドレスを表示しておく */
+            printf("%s", email);
+            /* if (suffix[0]) {
+                printf("-%s", suffix);
+            } */
+            if (auth)
+                printf("<br>(新規作成:New Account)");
+        }
+	if (prm[i][0])
+          printf("</td></tr>");
+	printf("\n");
+    }
+    
+    printf("</table>\n");
+    if (force)
+        printf("<input name=force type=hidden value=ON>\n");
+    if (auth) {
+        char *a[] = {"basic", "unix"};
+        printf("<input type=hidden name=auth value=\"%s\">\n", a[auth-1]);
+    }
+    printf("<input name=OK value=OK type=submit>\n");
+    printf("<input name=RESET value=RESET type=reset>\n");
+    printf("</form>\n");
+    fflush(stdout);
+}
+
+char *decode(char *code) {
+    int l=1+strlen(code);
+    int i, c, d;
+    char *ret = (char*)malloc(l*sizeof(char));
+    char *p = code;
+    memset(ret, 0, l);
+    for (i=0; i<strlen(code); i++) {
+	if (code[i] == '+') code[i] = ' ';
+    }
+    while (code[0] && (p=strchr(code, '%'))
+           && ishexa(*(p+1)) && ishexa(*(p+2))) {
+        *(p++) = '\0';
+        strncat(ret, code, l);
+        c = (islower(*p) ? toupper(*p) : *p) - '0';
+        p++;
+        d = (islower(*p) ? toupper(*p) : *p) - '0';
+        if (c > 9) c -= ('A'-'9'-1);
+        if (d > 9) d -= ('A'-'9'-1);
+        ret[strlen(ret)] = c*16+d;
+        code = p+1;
+    }
+    if (code[0]) strncat(ret, code, l);
+    return ret;
+}
+
+#define BSIZE	8192
+char **decode_post() {
+    char *buf = (char*)malloc(BSIZE*sizeof(char));
+    char **post, *p = buf;
+    int n=0, i;
+    post = (char**)calloc(1, sizeof(char*));
+    *buf = '\0';
+    fgets(buf, BSIZE, stdin);
+    if (strchr("\n\r", buf[strlen(buf)-1])) /* chop */
+        buf[strlen(buf)-1] = '\0';
+    while (buf[0] && NULL != (p=strchr(buf, '&'))) {
+        *p = '\0';
+        post[n] = (char*)malloc((p-buf+1)*sizeof(char));
+        strcpy(post[n], buf);
+        n++;
+        post = (char**)realloc(post, (1+n)*sizeof(char*));
+        buf = 1+p;
+    }
+    if (buf[0]) post[n++] = buf;
+    /* decode URL encoded */
+    for (i=0; i < n; i++) {
+        char *p;
+        p=post[i];
+        post[i] = decode(p);
+    }
+    post[i] = "";               /* terminator */
+    return post;
+}
+
+void footer() {
+    puts("</body>\n</html>");
+    fflush(stdout);
+}
+
+void fail() {
+    printf("パスワード更新に失敗しました<br>\n");
+    printf("<a href=\"./\">やり直し</a><br>\n");
+    footer();
+    exit(1);
+}
+void success(char *email) {
+    printf("<hr>メイルアカウント %s 用のパスワード更新は完了しました。<br>\n",
+           email);
+    footer();
+    exit(0);
+}
+
+int apopfile_existp(char *home, char *suffix, uid_t uid) {
+    struct stat st;
+    int s;
+    int len = strlen(home) + 1
+        + strlen(APOPFILEBASE) + strlen(suffix) + 3;
+    char *apopfile = (char*)malloc(len);
+    if (suffix[0]) {
+        snprintf(apopfile, len, "%s/%s%c%s%c",
+                 home, APOPFILEBASE, XADDR_DELIM, suffix, 0);
+    } else {
+        snprintf(apopfile, len, "%s/%s%c", home, APOPFILEBASE, 0);
+    }
+    seteuid(uid);
+    s = stat(apopfile, &st);
+    seteuid(0);
+    memset(apopfile, '\0', strlen(apopfile));
+    free(apopfile);
+    return !s;
+}
+
+#ifndef QMAILCONTROL
+# define QMAILCONTROL "/var/qmail/control"
+#endif
+#ifndef MAILTMPLEN
+# define MAILTMPLEN 1024
+#endif
+
+/* Convert virtual domain user
+ */
+char* conv_virtualdomain(char *account) {
+  char *dom = strchr(account, '@'), *p;
+  char vd[MAILTMPLEN+1], rewrite[MAILTMPLEN+1], previous[MAILTMPLEN+1];
+  FILE *vdfd;
+  int match=0;
+  char buf[MAILTMPLEN+1], *s;
+  snprintf(vd, MAILTMPLEN, "%s/%s", QMAILCONTROL, "virtualdomains");
+  if (NULL == dom) return account;
+  dom++;		/* set position of domain part beginning */
+  if (dom && NULL != (vdfd = fopen (vd, "r"))) {
+    int l = strlen(dom);
+    int L = strlen(account);
+    while ((s=fgets(buf, MAILTMPLEN, vdfd))) {
+      if (p=strchr(s, '#'))
+        *p = '\0';			/* zap comments */
+      if (!strchr(buf, ':'))
+        continue;
+      while (s && (strrchr(s, '\n') || strrchr(s, '\r') || strrchr(s, ' ')))
+        s[strlen(s)-1] = '\0';
+      if (!strncmp(account, s, L) && s[L] == ':' && s[L+1]) { /* user matches */
+	match = 3;
+        snprintf(rewrite, MAILTMPLEN, "%s-%s", s+L+1, account);
+	break;
+      }
+      if (!strncmp(dom, s, l) && s[l] == ':' && s[l+1]) { /* domain matches */
+        match = 2;
+	snprintf(rewrite, MAILTMPLEN, "%s%c%s", s+l+1, XADDR_DELIM, account);
+	continue;
+      }
+      if (match < 2 && s[0] == '.') { /* if domain described in wildcard */
+        if (p=strchr(s, ':')) {
+	  *p = '\0';
+	  if (!strcmp(dom+(strlen(dom)-strlen(s)), s)) {
+	    if (match == 0
+	        || strlen(previous) < strlen(s)) {
+	      match = 1;
+	      strncpy(previous, s, MAILTMPLEN);
+	      snprintf(rewrite, MAILTMPLEN, "%s%c%s", p+1, XADDR_DELIM, account);
+	    }
+	  }
+	}
+      }
+    }
+    fclose(vdfd);
+    if (match) {
+      p = strchr(rewrite, '@');
+      /* fprintf(stderr, "m=%d, rwr=[%s]\n", match, rewrite); */
+      if (p) {
+        *p = '\0';
+      }
+      /* fprintf(stderr, "rwr=[%s]\n", rewrite); */
+      s = malloc(strlen(rewrite)+1);
+      strncpy(s, rewrite, strlen(rewrite)+1);
+      memset(vd, 0, sizeof(vd));
+      memset(rewrite, 0, sizeof(rewrite));
+      memset(previous, 0, sizeof(previous));
+      return s;
+    }
+  }
+  /* Then, compare with locals */
+  snprintf(vd, MAILTMPLEN, "%s/%s", QMAILCONTROL, "locals");
+  if (NULL != (vdfd=fopen(vd, "r"))) {
+    while (s=fgets(buf, MAILTMPLEN, vdfd)) {
+      if (p=strchr(s, '#')) *p = '\0'; /* zap after comment mark # */
+	while (*s && (strrchr(s, '\r')||strrchr(s, '\n')
+			||strrchr(s, ' ')||strrchr(s, '\t'))) {
+	  *(s+strlen(s)-1) = '\0';
+	}
+	while (*s && (*s == '\t' || *s == ' ')) s++;
+	if (!strncmp(s, dom, strlen(s))) {	/* matches with local domain */
+	  int len = dom-account-1;
+	  p = (char*)malloc(len+1);
+	  memset(p, '\0', len+1);
+	  strncpy(p, account, len);
+	  return p;
+	}
+      }
+  }
+  return NULL; /* invalid domain */
+  /* return account; return itself */
+}
+
+void apopcall(char **args) {
+    int i=0, sc=0;
+    pid_t pid;
+    char *email="", *suffix="", *pass="", *new="", *new2 = "", *home="";
+    char buf[BUFSIZ], auth, *user;
+    FILE *child, *result;
+    while (args[i][0]) {
+        /* printf("[%s]<br>\n", args[i]); */
+        if (!strncmp("email=", args[i], 6)) {
+            email = args[i]+6;
+        } else if (!strncmp("suffix=", args[i], 7)) {
+            suffix = args[i]+7;
+        } else if (!strncmp("pass=", args[i], 5)) {
+            pass = args[i]+5;
+        } else if (!strncmp("new=", args[i], 4)) {
+            new = args[i]+4;
+        } else if (!strncmp("new2=", args[i], 5)) {
+            new2 = args[i]+5;
+        } else if (!strncmp("auth=", args[i], 5)) {
+            /* "this" or "base" or "unix" */
+            auth = args[i][5];
+        }
+        i++;
+    }
+    /* Make a backup of original e-mail address */
+    /* user = (char*)malloc(1+strlen(email));
+       strcpy(user, email);
+     */
+    user = conv_virtualdomain(email);
+    if (NULL == user) {
+      printf("そのようなドメインは無効です(%s)<br>\n", strchr(email, '@'));
+      printf("入力したメイルアドレスを確認してやり直してください.<br>\n");
+      fail();
+    }
+    if (strchr(user, XADDR_DELIM)) {
+	char *p = malloc(1+strlen(user));
+	char *q = NULL;
+	struct passwd *pwd;
+	    /* printf("user=[%s]<br>\n", user); */
+
+	memset(p, '\0', 1+strlen(user));
+	strcpy(p, user);
+	while (!(pwd=getpwnam(p)) && (q=strrchr(p, XADDR_DELIM))) {
+	    fflush(stdout);
+	    *q = '\0';
+	}
+	if (pwd && q) {
+	    q = user+(q-p)+1;
+	    user=p;
+	    suffix=q;
+	}
+    }
+    if (user[0] && new[0] && new2[0]) {
+        int tochild[2], toparent[2];
+        pid_t pid;
+        int argc=0;
+        char **argv;
+        struct passwd *pswd;
+	char *pstr;
+
+        if (!(pswd=getpwnam(user))) {
+            printf("Unkown user %s.\n", user);
+            fflush(stdout);
+            fail();
+        }
+	pstr = pswd->pw_passwd;
+#ifdef SHADOW_PASSWD
+	{  struct spwd *ss = getspnam(user);
+	   pstr = (char*)ss->sp_pwdp;
+	}
+#endif
+        home=pswd->pw_dir;
+        argv = (char**)calloc(4, sizeof(char*));
+        argv[argc++] = "apoppasswd";
+        argv[argc++] = "-s";
+        argv[argc++] = "-c";
+        /* if old password does not exist,
+           then check UNIX password */
+#if 0
+        if (apopfile_existp(home, suffix, pswd->pw_uid)) { /* no apop-ext exists */
+            /* そのまま */
+        } else if (apopfile_existp(home, "", pswd->pw_uid)) {/* check base mail password */
+            argv = (char**)realloc(argv, (argc+2)*sizeof(char*));
+            argv[argc++] = "-b";
+        }
+#endif
+        switch (auth) {
+        case 'b': case 'B':
+            if (apopfile_existp(home, "", pswd->pw_uid)) {
+                argv = (char**)realloc(argv, (argc+2)*sizeof(char*));
+                argv[argc++] = "-b";
+            } else {
+                printf("基本アドレスのパスワードファイルがありません<br>\n");
+                fail();
+            }
+            break;
+        case 'u': case 'U':
+            if (strcmp(pstr, (char*)crypt(pass, pstr))) {
+                printf("UNIX Password not correct.<br>\n");
+                /* printf("[%s]vs.[%s]<br>\n",
+                   pswd->pw_passwd, crypt(pass, pswd->pw_passwd)); */
+                printf("UNIXパスワードと一致しません.<br>\n");
+                fflush(stdout);
+                fail();
+            }
+        }
+
+        if (strlen(new) < 8 || strlen(new2) < 8) {
+            printf("New mail password must be more than 7 characters.<br>\n");
+            printf("メイルパスワードは8文字以上にしてください。<br>\n");
+            fflush(stdout);
+            fail();
+        }
+        if (suffix[0]) {
+            argv = (char**)realloc(argv, (argc+3)*sizeof(char*));
+            argv[argc++] = "-e";
+            argv[argc++] = suffix;
+                
+        }
+        argv[argc++] = NULL;
+        if (setgid(pswd->pw_gid) || 0 != setuid(pswd->pw_uid)) {
+            printf("Cannot switch to %s\n", user);
+	    printf("uid=%d, gid=%d<br>\n", pswd->pw_gid, pswd->pw_uid);
+	    printf("メイルパスワード変更サーバの設定不良の可能性があるので<br>\n");
+	    printf("お手数ですがこの画面のコピーを添えてシステム管理者");
+	    printf("まで御連絡下さい。<br>\n");
+            fflush(stdout);
+            fail();
+        }
+
+        /* OK, start apopasswd */
+        if (pipe(tochild)+pipe(toparent)) {
+            printf("Cannot create pipe\n");
+            fail();
+        }
+        if ((pid=fork()) > 0) {
+            FILE *child = fdopen(tochild[1], "w");
+            close(tochild[0]);
+            close(toparent[1]);
+            fprintf(child, "PASS %s\nNEW %s\nNEW2 %s\n",
+                    pass, new, new2);
+            fflush(child);
+            fclose(child);
+            
+        } else if (pid == -1) {
+            printf("Cannot fork\n");
+            fail();
+        } else {
+            char *pe = malloc(6+strlen(pswd->pw_dir));
+            close(tochild[1]);
+            close(toparent[0]);
+            dup2(tochild[0], 0);
+            dup2(toparent[1], 1);
+
+            /* setuid section */
+
+			strcpy(pe, "HOME=");
+			strcat(pe, pswd->pw_dir);
+            if (putenv(pe)) {
+				puts("ga-n! arichan gakkari<br>");
+			}
+            execv(APOPPASSWD, argv);
+
+            /* setuid section ends */
+            fprintf(stderr, "Cannot exec %s\n", APOPPASSWD);
+            fail();
+        }
+        result = fdopen(toparent[0], "r");
+        while (fgets(buf, BUFSIZ, result)) {
+            printf("%s<br>", buf);
+            fflush(stdout);
+            if (strstr(buf, "Success!")) {
+                printf("<br>Mail Password changed successfully!<br>\n");
+                sc++;
+                break;
+            } else if (strstr(buf, "mismatch")) {
+                printf("二個入れた新パスワードが一致しません.<br>\n");
+                break;
+            } else if (strstr(buf, "Illegal")) {
+                printf("照合用パスワードが違います.<br>--\n");
+                break;
+            } else if (strstr(buf, "does not exist")) {
+                /* try_overwrite(user, pass, new, new2, suffix); */
+                if (suffix[0]) {
+                    printf("%s-%s", user, suffix);
+                } else {
+                    printf("%s", user);
+                }
+                /* ここは来ないことになった(のはず) */
+                printf("というメイルアカウントは未作成です<br>\n");
+                printf("新規に作る場合はOKボタンをクリック\n");
+                put_form(email, pass, new, new2, suffix, 1, 0, 1);
+                fflush(stdout);
+            }
+        }
+        fclose(result);
+        while (wait(0) != pid) {sleep(1);fputc('.', stderr);}
+        if (sc) success(email); else fail();
+    } else if (user[0]) {
+        struct passwd *pw = getpwnam(user);
+        int auth=0;
+        if (!pw) {
+            printf("そのようなユーザはいません %s<br>\n", user);
+            fail();
+        }
+	home=pw->pw_dir;
+        
+	printf("%s というメイルアドレスの<br>\n", email);
+        printf("メイル専用パスワードを変更します.<br>\n");
+        printf("メイルパスワードとUNIXパスワードの違いに気をつけてください.<br>\n");
+        printf("新パスワードは8文字以上にしてください.<br>\n");
+        printf("New password must be more than or equal to 8 characters.<br>\n");
+        if (apopfile_existp(home, suffix, pw->pw_uid)) {
+            auth = 0;           /* this password file */
+	    printf("「古いメイルパスワード」には、現在<br>\n");
+	    printf("<tt>%s</tt><br>\n", email);
+	    printf("を読むために指定しているパスワードを入力します。");
+        } else if (apopfile_existp(home, "", pw->pw_uid)) {
+            auth = 1;           /* basic mail address password */
+	    printf("今回は本人認証として基本メイルアドレスのパスワードを");
+	    printf("入力しますが、新しくパスワードを設定するのは<br>\n");
+	    printf("<tt>%s</tt><br>\n", email);
+	    printf("用のパスワードです。基本メイルアドレスのパスワードは");
+	    printf("変わりませんので注意してください。");
+        } else {
+            auth = 2;           /* UNIX login */
+        }
+        put_form(email, "", "", "", suffix, 0, auth, 0);
+        footer();
+        exit(0);
+    }
+    printf("user=[%s]\n", user);
+}
+
+int main(int argc, char* argv[]) {
+    char *method = getenv("REQUEST_METHOD");
+    char **args;
+    myname = argv[0];
+    if (method && strcmp(method, "POST") != 0) {
+        printf("This program should be used in method:POST.\n");
+        fail();
+    }
+    printf("Content-type: text/html; charset=EUC-JP\n\n");
+    printf("<html>\n<head><title>Change Password</title></head>\n");
+    printf("<body style=\"background: #f0ffff;\">\n");
+    if (getenv("SSL_CIPHER") && getenv("SSL_PROTOCOL")) {
+        args = decode_post();
+        apopcall(args);
+    } else {
+        printf("This program can be used only via SSL connection.<br>\n");
+        printf("このユーティリティはSSL接続時のみ有効です.<br>\n");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/apoppasswd	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,210 @@
+#!/usr/local/bin/perl
+# Customize these variables.
+# If you change APOPFILEBASE, change the same variable in apopcall.c too.
+# See http://www.gentei.org/~yuuji/software/imapext/
+
+$HOME=$ENV{"HOME"};
+
+$DEFAULTMAILDIR = "Maildir";	# Must be same as ../src/osdep/unix/Makefile
+
+$APOPFILEBASE = ".apop";	# "$HOME/$APOPFILEBASE" is the password file
+# $APOPFILEBASE = "$DEFAULTMAILDIR/apop";
+# $APOPFILEBASE = "Mail/apop";
+
+$ENCODER = "cat";
+# $ENCODER = "gzip";
+# $ENCODER = "uuencode $$|gzip";
+
+$DECODER = "cat";
+# $DECODER = "gzip -dc";
+# $DECODER = "gzip -dc | uudecode";
+
+$DOTQMAIL = ".qmail";		# qmail
+# $DOTQMAIL = ".forward";	# Postfix
+
+$XADDR_DELIM = "-";		# qmail
+# $XADDR_DELIM = "+";		# Postfix
+
+$HERE = ".";			# qmail
+# $HERE = "~";			# Postfix
+
+$EXT = "";
+$force = 0;
+$base = 0;
+
+$APOPFILE = "$HOME/$APOPFILEBASE";
+
+sub handler {
+	system "stty echo";
+	print STDERR "Abort:\n";
+	exit 1;
+}
+
+$SIG{'INT'} = $SIG{'KILL'} = $SIG{'QUIT'} = $SIG{'HUP'} = 'handler';
+
+while ($_=$ARGV[0], /^-.+/ && shift) {
+    if (/^-e/) {
+	$APOPFILE .= $XADDR_DELIM . ($EXT=shift);
+    } elsif (/^-b/) {
+	$base++;
+    } elsif (/^-c/) {
+	$create++;
+    } elsif (/^-s/) {
+	$stream++;
+	# and exit;
+    } elsif (/^-h/) {
+	&usage; # and exit
+    }
+}
+
+sub checkmaildir {
+    local($dotqmail) = ("$HOME/$DOTQMAIL");
+    local($maildir) = ($DEFAULTMAILDIR);	  # default
+    $dotqmail .= "$XADDR_DELIM$EXT" if $EXT;
+    $maildir .= "-$EXT" if $EXT;
+    unless (-f "$dotqmail") {
+	if ($create) {
+	    if (open(DQMAIL, "> $dotqmail")) {
+		print DQMAIL "$HERE/$maildir/\n";
+		print "File [$dotqmail] created\n";
+		close(DQMAIL);
+	    }
+	} else {
+	    print "$dotqmail file does not exist.\n";	# should go to stdout
+	    print "Your should create $maildir first!\n";
+	    print "(-c option automatically makes it)\n";
+	    exit 1;
+	}
+    }
+    if (-s $dotqmail) {
+	$maildir='';
+	if (open(DQMAIL, "< $dotqmail")) {
+	    while (<DQMAIL>) {
+		s/[\r\n \t]*$//g;
+		next if /#/;
+		next unless m,\./.*/,;
+		chop;			  # strip trailing "/"
+		$maildir = $_;
+		last;
+	    }
+	    close(DQMAIL);
+	    $maildir = $DEFAULTMAILDIR if $maildir eq '';
+	    unless (-d "$HOME/$maildir"
+		    && -d "$HOME/$maildir/new"
+		    && -d "$HOME/$maildir/cur"
+		    && -d "$HOME/$maildir/tmp") {
+		if ($create) {
+		    mkdir "$HOME/$maildir", 0700;
+		    mkdir "$HOME/$maildir/new", 0700;
+		    mkdir "$HOME/$maildir/cur", 0700;
+		    mkdir "$HOME/$maildir/tmp", 0700;
+		    print "Maildir [$maildir/] created\n";
+		} else {
+		    print "Maildir($maildir) does not exist\n";
+		    print "Your should do maildirmake $maildir first!\n";
+		    print "(-c option automatically makes it)\n";
+		    exit 1;
+		}
+	    }
+	}
+    }
+}
+
+sub usage {
+    local($mydir, $myname) = ($0 =~ m,(.*)/(.*),);
+    print<<_EOU_;
+$myname	Change Mail password for imap-4.7+qmailapop
+Usage:	$myname [options]
+Options are...
+	-e EXT		Set target email address to "user-EXT"
+	-c		If no .qmail file and Maildir, create them
+
+_EOU_
+    exit 0;
+}
+
+if ($stream) {
+    &stream;
+    exit; # not reached
+}
+$OK=0;
+until ($OK) {
+    system "stty -echo";
+    print STDERR "Enter APOP Password: ";
+    $new1 = <>;
+    print STDERR "\n";
+    if (length($new1) == 1) {
+	print STDERR "Canceled\n";
+	exit 1;
+    } elsif (length($new1) < 9) {
+	print STDERR "Password is too short!  Please use more than 8 chars.\n";
+	next;
+    }
+    print STDERR "Again APOP Password: ";
+    $new2 = <>;
+    if ($new1 eq $new2) {
+	$OK=1;
+    } else {
+	print STDERR "\nPassword mismatch! Try again.\n";
+    }
+}
+#OK
+&checkmaildir;
+system "stty echo";
+open(NP, "| $ENCODER > $APOPFILE") || die "Cannot write on $APOPFILE\n";
+print NP "$new1";
+close(NP);
+chmod 0600, $APOPFILE;
+print STDERR "\nUpdated APOP password successfully.\n";
+
+sub stream {				  # Must match with old password
+    local($PASS, $old, $new1, $new2, $master) = (0);
+    local($masterfile) = ($APOPFILE);
+    $masterfile = "$HOME/$APOPFILEBASE" if $base;
+    exit 1 if ($> == 0);
+    while (<>) {
+	chop;
+	if (/^PASS (.*)$/i) {
+	    $old = $1;
+	} elsif (/^NEW (.*)/i) {
+	    $new1 = $1;
+	} elsif (/^NEW2 (.*)/i) {
+	    $new2 = $1;
+	}
+	last if ("$new1" ne "" && "$new2" ne "");
+    }
+    if (-s $APOPFILE || ($base && -f $masterfile)) { # Already exist
+	if (open(OLD, "$DECODER $masterfile |")) {
+	    ($master = <OLD>) =~ s/[\n\r]$//g;
+	    close(OLD);
+	} else {
+	    print "Old password file corrupted.\n";
+	    print "Please ask to administrator.\n";
+	    exit 1;
+	}
+	if ($master ne $old) {
+	    print "Illegal password\nBye\n";
+	    exit 1;
+	}
+    } 
+    if ($new1 ne $new2) {
+	print "Password(new) mismatch\nBye\n";
+	exit 1;
+    }
+    # OK, now begin to create!
+    &checkmaildir;
+    if (open(P, "| $ENCODER > $APOPFILE")) {
+	# open success
+	print P "$new1\n";
+	close(P);
+	chmod 0600, $APOPFILE;
+	if (-s $APOPFILE) {
+	    print "Success!\n";
+	    exit 0;
+	}
+    } else {
+	print "Cannot output to $APOPFILE\nBye\n";
+	exit 1;
+    }
+    exit 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/deapop	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,4 @@
+#!/bin/sh
+# deapop script for plain password file
+cat "$@"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/deapop.gzip	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,4 @@
+#!/bin/sh
+# deapop script for gzipped password file
+gzcat "$@"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/index.html	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,65 @@
+<html>
+<head>
+<title>
+APOP Password
+</title>
+<style type="text/css">
+<!--
+.e {color: red; text-decoretion: underline;}
+-->
+</style>
+</head>
+
+<body bgcolor="azure">
+<p>$B$"$J$?$N%a%$%k%"%I%l%9@lMQ$N%Q%9%o!<%I$r@_Dj$^$?$O99?7$7$^$9!#(B</p>
+<form method=POST action="./apopcall.cgi">
+<table border="1">
+<tr><td>$B%a%$%k%"%I%l%9(B:<br>User Name:</td>
+ <td><input name="email" size="40" maxlength="40"></td></tr>
+</table>
+<input name="OK" type="submit" value="OK">
+<input name="OK" type="reset" value="Clear">
+</form>
+<ul>
+ <li> $B=i$a$FMxMQ$9$k>l9g(B
+      <p>$B%Q%9%o!<%I$r@_Dj$7$?$$%a%$%k%"%I%l%9$rF~NO$7$F$/$@$5$$!#(B
+      $B%a%$%k@lMQ$N%Q%9%o!<%I$r2a5n$K@_Dj$7$F$$$J$$>l9g$O!"(B
+      $B<!$N2hLL$GK\?MG'>Z$H$7$F(BUNIX$B%Q%9%o!<%I(B($B%5!<%P$K(B
+      $B%m%0%$%s$9$k$H$-$N$b$N(B)$B$rF~NO$7$F$/$@$5$$!#(B</p>
+ <li> $B3HD%%a%$%k%"%I%l%9$N;XDj(B
+      <p>$B4pK\%a%$%k%"%I%l%9$N%f!<%6L>$N8e$m$K(B<span class="e">-$B3HD%;R(B
+      </span> ($B%O%$%U%s(B+$B3HD%;R(B)$B$r2C$($?%"%I%l%9$,3HD%%a%$%k%"%I%l%9$K$J(B
+      $B$j$^$9!#(B<br>
+      $BNc(B:<br>
+      $B4pK\%"%I%l%9(B : user@xxx.hogehoge.ac.jp<br>
+      $B3HD%%"%I%l%9(B : user-foo@xxx.hogehoge.ac.jp<br>
+      ($B$3$N>l9g$N3HD%;R$O(B foo)
+      </p>
+      <p>$B3HD%%a%$%k%"%I%l%9$O!"3HD%;RItJ,$rJQ$($k$3$H$G(B
+      $B2?8D$G$b:n$k$3$H$,$G$-$^$9!#(B
+      $B?75,$K:n@.$7$?$$$H$-$O!"3HD%%a%$%k%"%I%l%9$rF~NO$7$F(BOK$B$r(B
+      $B2!$7$F$/$@$5$$!#?7$7$$%a%$%k%\%C%/%9$r<+F0E*$K:n@.(B
+      $B$9$k$HF1;~$K?73HD%%a%$%k%"%I%l%9@lMQ$N%Q%9%o!<%I$b9T$J$$$^$9!#(B
+      </p>
+</ul>
+<p>$B!Z(B<a href="qmapmore.html">
+$B$3$N%5!<%P$GMxMQ$G$-$k%a%$%k%"%I%l%9$K$D$$$F(B</a>$B![(B</p>
+<hr>
+<ul>
+ <li> At your first trial to set mail password
+      <p>Push [OK] button with your mail address.  We call your
+      mail address <em>YourName</em>@xxx.yyy.jp as `basic email address'.<p>
+
+ <li> To create extensional email address<br>
+
+      <p>On our system, you can have more than one email addresses.  You
+      can create any (mail)account name "YourName-xxx"(where xxx is
+      any extensional word you might give) which will be delivered to you.  To
+      create an extesional email address and/or change the password for
+      it, put the extensional email address in the input window.</p>
+</ul>
+
+<hr>
+<!--#include virtual="/~yuuji/signature.html"-->
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/pop3-age	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,62 @@
+#!/bin/sh -
+# A sample "POP before SMTP"-enabler script for tcp_wrappers
+# This script should be installed in /usr/local/etc
+# If you are thinking of using this script on heavily loaded host,
+# you had better to choose tcpserver instead of tcp_wrappers.
+# 
+ALLOWTMP="/var/log/ATMP"
+if [ -f /usr/local/etc/hosts.allow ]; then
+ ALLOW="/usr/local/etc/hosts.allow"
+else
+ ALLOW=/etc/hosts.allow
+fi
+ALLOWSRC=${ALLOW}.src
+ALLOWNEW=${ALLOW}.new
+
+# for debug
+# (env;echo "1=$1") | Mail -s pop3access yuuji
+
+case $0 in
+  *record)
+	echo "tcp-env : $RELAYCLIENT : setenv = RELAYCLIENT" >> $ALLOWTMP.1
+	;;
+  *age)
+	rm -f $ALLOWTMP.2
+	[ -f $ALLOWTMP.1 ] && mv -f $ALLOWTMP.1 $ALLOWTMP.2
+	;;
+  *)
+	# else generate master hosts.allow file
+	;;
+esac
+touch $ALLOWTMP.1 $ALLOWTMP.2
+echo "#
+# DO NOT EDIT THIS FILE!
+# This file is generated from $ALLOWSRC file.
+# Edit it!
+#" > $ALLOWNEW
+(cat $ALLOWTMP.[12] | sort -u; cat $ALLOWSRC) >> $ALLOWNEW
+/bin/mv -f $ALLOWNEW $ALLOW
+
+# pop3-{age,update,record} for tcp_wrappers ends here
+# The following section is the sample routine for tcpserver(ucsp-tcp)
+# If you use tcpserver, replace the above section after "case $0...esac"
+# by the following section.
+# Sample code was contributed by pirozeau(pirozeau@banana-fish.com).
+
+#TCPREMOTEIP=${TCPREMOTEIP:-undefined}
+#RELAYCLIENT=${RELAYCLIENT:-$TCPREMOTEIP}
+#ALLOW=/usr/local/etc/smtprule
+#case $0 in
+#  *record)
+#	echo "$RELAYCLIENT:allow,RELAYCLIENT=\"\"" >> $ALLOWTMP.1
+#	;;
+#  *age)
+#	rm -f $ALLOWTMP.2
+#	[ -f $ALLOWTMP.1 ] && mv -f $ALLOWTMP.1 $ALLOWTMP.2
+#	;;
+#  *)
+#	# else generate master tcprule file
+#	;;
+#esac
+#touch $ALLOWTMP.1 $ALLOWTMP.2
+#(cat $ALLOWTMP.[12] | sort -u; cat ${ALLOW}) | /usr/local/bin/tcprules ${ALLOW}.cdb ${ALLOW}.tmp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/pop3-record	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,62 @@
+#!/bin/sh -
+# A sample "POP before SMTP"-enabler script for tcp_wrappers
+# This script should be installed in /usr/local/etc
+# If you are thinking of using this script on heavily loaded host,
+# you had better to choose tcpserver instead of tcp_wrappers.
+# 
+ALLOWTMP="/var/log/ATMP"
+if [ -f /usr/local/etc/hosts.allow ]; then
+ ALLOW="/usr/local/etc/hosts.allow"
+else
+ ALLOW=/etc/hosts.allow
+fi
+ALLOWSRC=${ALLOW}.src
+ALLOWNEW=${ALLOW}.new
+
+# for debug
+# (env;echo "1=$1") | Mail -s pop3access yuuji
+
+case $0 in
+  *record)
+	echo "tcp-env : $RELAYCLIENT : setenv = RELAYCLIENT" >> $ALLOWTMP.1
+	;;
+  *age)
+	rm -f $ALLOWTMP.2
+	[ -f $ALLOWTMP.1 ] && mv -f $ALLOWTMP.1 $ALLOWTMP.2
+	;;
+  *)
+	# else generate master hosts.allow file
+	;;
+esac
+touch $ALLOWTMP.1 $ALLOWTMP.2
+echo "#
+# DO NOT EDIT THIS FILE!
+# This file is generated from $ALLOWSRC file.
+# Edit it!
+#" > $ALLOWNEW
+(cat $ALLOWTMP.[12] | sort -u; cat $ALLOWSRC) >> $ALLOWNEW
+/bin/mv -f $ALLOWNEW $ALLOW
+
+# pop3-{age,update,record} for tcp_wrappers ends here
+# The following section is the sample routine for tcpserver(ucsp-tcp)
+# If you use tcpserver, replace the above section after "case $0...esac"
+# by the following section.
+# Sample code was contributed by pirozeau(pirozeau@banana-fish.com).
+
+#TCPREMOTEIP=${TCPREMOTEIP:-undefined}
+#RELAYCLIENT=${RELAYCLIENT:-$TCPREMOTEIP}
+#ALLOW=/usr/local/etc/smtprule
+#case $0 in
+#  *record)
+#	echo "$RELAYCLIENT:allow,RELAYCLIENT=\"\"" >> $ALLOWTMP.1
+#	;;
+#  *age)
+#	rm -f $ALLOWTMP.2
+#	[ -f $ALLOWTMP.1 ] && mv -f $ALLOWTMP.1 $ALLOWTMP.2
+#	;;
+#  *)
+#	# else generate master tcprule file
+#	;;
+#esac
+#touch $ALLOWTMP.1 $ALLOWTMP.2
+#(cat $ALLOWTMP.[12] | sort -u; cat ${ALLOW}) | /usr/local/bin/tcprules ${ALLOW}.cdb ${ALLOW}.tmp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/pop3-record.postfix	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,29 @@
+#!/bin/sh -
+# A sample "POP before SMTP"-enabler script for Postfix
+# This script should be installed in /usr/local/etc.
+# This script assumes 
+# 
+POSTFIXDIR=/etc/postfix
+POSTFIXBIN=/usr/libexec/postfix
+PATH=$POSTFIXBIN\:$PATH
+OKDIR=/var/log
+OKCLIENT=$OKDIR/ATMP
+CLIENTACCESS=$POSTFIXDIR/client_access
+
+case $0 in
+  *record)
+	echo "$RELAYCLIENT	OK" >> $OKCLIENT.1
+	;;
+  *age)
+	rm -f $OKCLIENT.2
+	[ -f $OKCLIENT.1 ] && mv -f $OKCLIENT.1 $OKCLIENT.2
+	echo '' > $CLIENTACCESS
+	# rm -f $CLIENTACCESS.db
+	postmap hash:$CLIENTACCESS
+	;;
+  *)
+	# else generate master client_access.db
+	;;
+esac
+touch $OKCLIENT.1 $OKCLIENT.2
+cat $OKCLIENT.1 $OKCLIENT.2 | postmap -r -i hash:$CLIENTACCESS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/pop3-update	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,62 @@
+#!/bin/sh -
+# A sample "POP before SMTP"-enabler script for tcp_wrappers
+# This script should be installed in /usr/local/etc
+# If you are thinking of using this script on heavily loaded host,
+# you had better to choose tcpserver instead of tcp_wrappers.
+# 
+ALLOWTMP="/var/log/ATMP"
+if [ -f /usr/local/etc/hosts.allow ]; then
+ ALLOW="/usr/local/etc/hosts.allow"
+else
+ ALLOW=/etc/hosts.allow
+fi
+ALLOWSRC=${ALLOW}.src
+ALLOWNEW=${ALLOW}.new
+
+# for debug
+# (env;echo "1=$1") | Mail -s pop3access yuuji
+
+case $0 in
+  *record)
+	echo "tcp-env : $RELAYCLIENT : setenv = RELAYCLIENT" >> $ALLOWTMP.1
+	;;
+  *age)
+	rm -f $ALLOWTMP.2
+	[ -f $ALLOWTMP.1 ] && mv -f $ALLOWTMP.1 $ALLOWTMP.2
+	;;
+  *)
+	# else generate master hosts.allow file
+	;;
+esac
+touch $ALLOWTMP.1 $ALLOWTMP.2
+echo "#
+# DO NOT EDIT THIS FILE!
+# This file is generated from $ALLOWSRC file.
+# Edit it!
+#" > $ALLOWNEW
+(cat $ALLOWTMP.[12] | sort -u; cat $ALLOWSRC) >> $ALLOWNEW
+/bin/mv -f $ALLOWNEW $ALLOW
+
+# pop3-{age,update,record} for tcp_wrappers ends here
+# The following section is the sample routine for tcpserver(ucsp-tcp)
+# If you use tcpserver, replace the above section after "case $0...esac"
+# by the following section.
+# Sample code was contributed by pirozeau(pirozeau@banana-fish.com).
+
+#TCPREMOTEIP=${TCPREMOTEIP:-undefined}
+#RELAYCLIENT=${RELAYCLIENT:-$TCPREMOTEIP}
+#ALLOW=/usr/local/etc/smtprule
+#case $0 in
+#  *record)
+#	echo "$RELAYCLIENT:allow,RELAYCLIENT=\"\"" >> $ALLOWTMP.1
+#	;;
+#  *age)
+#	rm -f $ALLOWTMP.2
+#	[ -f $ALLOWTMP.1 ] && mv -f $ALLOWTMP.1 $ALLOWTMP.2
+#	;;
+#  *)
+#	# else generate master tcprule file
+#	;;
+#esac
+#touch $ALLOWTMP.1 $ALLOWTMP.2
+#(cat $ALLOWTMP.[12] | sort -u; cat ${ALLOW}) | /usr/local/bin/tcprules ${ALLOW}.cdb ${ALLOW}.tmp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/qmapmore.html	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,187 @@
+<html>
+<head>
+<title>
+APOP Password
+</title>
+<style type="text/css">
+<!--
+h1 {text-align: center; text-decoration: underline;}
+h2 {color: navy; background-color: lavender;}
+.e {color: red; text-decoretion: underline;}
+dt (background-color: yellow;}
+-->
+</style>
+</head>
+
+<body bgcolor="azure">
+<h1>
+ $BK\%a%$%k%5!<%P$K4X$9$kMxMQ<T>\:Y>pJs(B
+</h1>
+<p>$BL\<!(B</p>
+<ul>
+ <li> <a href="#extaddress">$BK\%5!<%P$GMxMQ$G$-$k%a%$%k%"%I%l%9(B</a>
+ <li> <a href="#APOP">$B%a%$%k<u?.;~$N%W%m%H%3%k$K$D$$$F(B</a>
+ <li> <a href="#forward">$BB>$N%a%$%k%5!<%P$X$NE>Aw(B</a>
+</ul>
+<hr>
+
+<h2>
+ <a name="extaddress">$BK\%5!<%P$GMxMQ$G$-$k%a%$%k%"%I%l%9(B</a>
+</h2>
+<p>$BK\%5!<%P$G$O%a%$%kG[Aw%7%9%F%`$H$7$F(Bqmail$B$rMxMQ$7$F$$$k$N$G!"(B
+$BMxMQ<T$N3'$5$s$O2?8D$G$b%a%$%k%"%I%l%9$r:n$k$3$H$,$G$-$^$9!#(B
+$B0J2<$N@bL@$G$O!"8D?M$N%a%$%k%"%I%l%9$N%"%+%&%s%HL>ItJ,$r(B
+<var>user</var>$B!"%I%a%$%sL>ItJ,$r(B <var>dokkano.ac.jp</var> $B$H(B
+$BI=$9$3$H$K$7$^$9!#$D$^$j!"Nc$G;HMQ$9$k%a%$%k%"%I%l%9$O(B
+<var>user@dokkano.ac.jp</var>$B$H$J$j$^$9!#$3$N%"%I%l%9$O8f<+?H$N$b$N$HCV(B
+$B$-49$($F@bL@$rFI$_?J$a$F$/$@$5$$!#(B</p>
+
+<dl>
+ <dt> $B!Z4pK\%a%$%k%"%I%l%9![(B
+ <dd> <p><var>user@dokkano.ac.jp</var>$B$r4pK\%a%$%k%"%I%l%9$H8F$S$^$9!#%"(B
+      $B%+%&%s%H:n@.$HF1;~$KL5>r7o$GMxMQ$G$-$k%a%$%k%"%I%l%9$G$9!#$3$N%"%I(B
+      $B%l%9$KFO$$$?%a%$%k$O%5!<%P>e$N$"$J$?@lMQ$N%a%$%k%\%C%/%9$KC_$($i$l(B
+      $B$^$9!#JL$N%"%I%l%9$KE>Aw$9$k$3$H$b2DG=$G$9$,!"J}K!$O8e=R$7$^$9!#(B</p>
+
+ <dt> $B!Z3HD%%a%$%k%"%I%l%9![(B
+ <dd> <p><var>user<span class="e">-xxx</span>@dokkano.ac.jp</var>$B$H$$$&(B
+      $B7A<0$N%"%I%l%9$r3HD%%a%$%k%"%I%l%9$H8F$S$^$9!#$"$J$?$N%"%+%&%s%HL>(B
+      $B$G;O$^$j!"$=$ND>8e$K%O%$%U%s(B(<span class="e">-</span>)$B$G6h@Z$C$FG$(B
+      $B0U$NJ8;zNs$,Mh$k%a%$%k%"%I%l%9$O!"A4$F$"$J$?08$KG[Aw$5$l$^$9!#(B
+      <var>user<span class="e">-xxx</span></var>$B$N(B<var>xxx</var>$B$NItJ,$O(B
+      <span class="e">$B3HD%;R(B</span>$B$H8F$S!"$I$s$JC18l$G$b9=$$$^$;$s!#(B
+      <var>user-123@dokkano.ac.jp, user-job@dokkano.ac.jp,
+      user-meeting@dokkano.ac.jp, ...</var>$B$J$I$J$I!"$I$s$J%a%$%k%"%I%l(B
+      $B%9$G$b<+J,MQ$K:n@.$9$k$3$H$,$G$-$^$9!#(B
+      </p>
+</dl>
+
+<p>$B3HD%%a%$%k%"%I%l%9$rMxMQ$9$k>l9g$O!":G=i$K$=$N%"%I%l%9$r<u$1<h$k%a%$(B
+$B%k%\%C%/%9$r:n$j$H$=$N%"%I%l%9<u?.MQ$N%Q%9%o!<%I$r@_Dj$9$kI,MW$,$"$j$^$9!#(B
+<a href="index.html">$B%a%$%k%Q%9%o!<%I@_Dj2hLL(B</a>$B$K$F!"$3$l$+$i<u$1<h$j(B
+$B$?$$%a%$%k%"%I%l%9$r(B<var>user<span
+class="e">-xxx</span>@dokkano.ac.jp</var> $B$N7A<0$GF~NO$7$F@h$K?J$a$P<+F0(B
+$BE*$K%a%$%k%\%C%/%9$N:n@.$^$G40N;$7$^$9!#$3$N$H$-!"$"$J$?K\?M$N3NG'$H$7$F(B
+$B4{B8$N(B<span class="e">$B4pK\%a%$%k%"%I%l%9$N%Q%9%o!<%I(B</span>$B$rF~NO$7$F$/(B
+$B$@$5$$!#(B</p>
+
+<h2>
+ <a name="APOP">$B%a%$%k<u?.;~$N%W%m%H%3%k$K$D$$$F(B</a>
+</h2>
+<p>$B8=:_9-$/MxMQ$5$l$F$$$k%a%$%k<u?.%W%m%H%3%k$G$"$k(BPOP3$B$O!"(B
+$B%Q%9%o!<%I$r$=$N$^$^$N7A(B($BJ?J8(B:$B%W%l%$%s%F%-%9%H(B)$B$G%M%C%H%o!<%/$KN.$7$F$7(B
+$B$^$&$N$G!"4JC1$KK5<u$5$l$k$*$=$l$,$"$j$^$9(B($B8=6b<+F0;YJ'5!$NA0$G0E>ZHV9f(B
+$B$r@<$K=P$7$J$,$i2!$7$F$$$k;Q$rA[A|$7$F$/$@$5$$(B)$B!#(B</p>
+
+<p>$B$=$N$h$&$J4m81@-$r9MN8$7$FK\%5!<%P$G$O0J2<$N@_Dj$r9T$J$C$F$$$^$9!#(B</p>
+<ul>
+ <li> POP3$B$O2f!9$NAH?%Fb%M%C%H%o!<%/$+$i$N$_MxMQ$r5v2D(B<br>
+      ($BFbIt%M%C%H%o!<%/$K$OIt30<T$O4JC1$K$OF'$_9~$a$J$$$N$G4vJ,0BA4$G$9(B)
+ <li> $B$=$l0J30$N>l=j$+$i$N<u?.$G$O(BAPOP$B$N$_$r5v2D(B
+</ul>
+<p>APOP$B$H$O%Q%9%o!<%I$r0E9f2=$7$F$d$j$H$j$9$k$h$&$K3HD%$7$?(BPOP3$B$G!"2>$K(B
+$BK5<u$5$l$?$H$7$F$b85$N%Q%9%o!<%I$O2rFI$G$-$^$;$s!#(BAPOP$B$rMxMQ$9$k>l9g$O$"(B
+$B$i$f$k>l=j$+$i$N%a%$%k$N<u?.$,2DG=$K$J$j$^$9!#0BA4@-$r9M$($k$H!"2>$KFbIt(B
+$B$+$i$7$+MxMQ$7$J$$>l9g$G$b(BAPOP$B$rMxMQ$5$l$k$3$H$r6/$/$*4+$a$7$^$9!#(B</p>
+
+<p>APOP$B$rMxMQ$9$k$?$a$NJ}K!$r@bL@$7$^$9!#$J$*!"0J2<$N%a%$%k%j!<%@$G$O(B
+APOP$B$,(B<span class="e">$BMxMQ$G$-$^$;$s(B</span>$B$N$G$4Cm0U$/$@$5$$!#(B</p>
+<dl>
+ <dt> $B!Z(BAPOP$B$K(B<span class="e">$BBP1~$7$F$$$J$$(B</span>$B<g$J%a%$%k%j!<%@![(B
+ <dd> Microsoft Outlook Express<br>
+      Microsoft Outlook<br>
+      Netscape Messenger
+ <dt> $B!Z(BAPOP$B$KBP1~$7$F$$$k<g$J%a%$%k%j!<%@![(B
+ <dd> <ul>
+       <li> Windows$BMQ(B<br>
+	    <a href="http://www.almail.com/">AL-Mail</a>
+	    ($B%7%'%"%&%'%"(B/$B3X@8!&3X=Q5!4XMxMQ$N$_L5NA(B),<br>
+	    <a href="http://www.rimarts.co.jp/becky-j.htm">Becky!</a>
+	    ($B%7%'%"%&%'%"(B),<br>
+	    <a href="http://denshin8.esprix.net/">$BEE?.H,9f(B</a>
+	    ($B%U%j!<%=%U%H%&%'%"(B),<br>
+	    <a href="http://www.eudora.ne.jp/">Eudora</a>
+	    (3$B<oN`$N%i%$%;%s%97ABV(B)
+       <li> UNIX$BMQ(B($B0J2<A4$F%U%j!<%=%U%H(B)<br>
+	    <a href="http://www.mew.org/index-j.html">Mew</a>,<br>
+	    <a href="http://www.gohome.org/wl/index.ja.html">
+	    Wanderlust</a>
+      </ul>
+</dl>
+<p>$B0J2<$K$$$/$D$+$N%a%$%k%j!<%@$N(BAPOP$B@_DjJ}K!$r<($7$^$9!#(B</p>
+<dl>
+ <dt> $B!L(BAL-Mail$B!M(B
+ <dd> <ol>
+       <li> $B@_Dj$7$?$$%"%+%&%s%H$rA*$V(B
+       <li> $B!V%D!<%k(B(T)$B!W"*!V%*%W%7%g%s(B(O)$B!W$G=P$FMh$k%"%+%&%s%H@_Dj%a(B
+	    $B%K%e!<$N!"!V%"%+%&%s%H!W2hLL$K$F1&2<$N!V9bEY$J@_Dj!W$r%/%j%C(B
+	    $B%/(B
+       <li> $B!V9bEY$J@_Dj!W%&%#%s%I%&$N:82<!V(BAPOP$B$GG'>Z!W$r%A%'%C%/(B
+      </ol>
+ <dt> $B!L(BBecky!$B!M(B
+ <dd> <ol>
+       <li> $B!V%D!<%k(B(T)$B!W"*!V@_Dj!W$G=P$k%&%#%s%I%&$G(B [$B%"%+%&%s%H(B]
+	    $B$rA*Br(B
+       <li> [$B%"%+%&%s%H(B]$B@_Dj%&%#%s%I%&$N2<$K$"$k(B [$B$=$NB>(B] $B$r(B
+	    $B%/%j%C%/(B
+       <li> $B%&%#%s%I%&2<It$N(B [APOP$B$r;H$&(B] $B$r%A%'%C%/(B
+      </ol>
+ <dt> $B!L(BEudora 4$B!M(B
+ <dd> <ol>
+       <li> $B!V%D!<%k(B(T)$B!W"*!V%Q!<%=%J%j%F%#(B(P)$B!W$G%"%+%&%s%HA*Br2hLL$r:8(B
+	    $BB&%&%#%s%I%&$K=P$9(B
+       <li> APOP$B@_Dj$7$?$$%"%+%&%s%H$r1&%/%j%C%/$7!VJQ99(B(P)$B!W$rA*$V(B
+       <li> $B!V%a!<%k$N<u?.!W%a%K%e!<$rA*Br(B
+       <li> $B%&%#%s%I%&$N0lHV2<$N(B [$BG'>ZJ}<0(B] $B$G(BAPOP$B$r%A%'%C%/(B
+      </ol>
+
+ <dt> $B!L(BMew$B!M(B
+ <dd> <p>~/.im/Config $B$N(B Imget.Src $B9T$N@_Dj$r0J2<$N$h$&$KJQ$($^$9!#(B</p>
+      <blockquote>
+       <p><tt>Imget.Src=pop/<span class="e">APOP</span>:user@$B%5!<%PL>(B</tt></p>
+      </blockquote>
+ <dt> $B!L(BWanderlust$B!M(B
+ <dd> <p>$B%U%)%k%@%P%C%U%!$G(B m a $B$7$F0J2<$N$h$&$K%U%)%k%@$rDI2C$7$^$9!#(B</p>
+      <blockquote>
+       <p><tt>&amp;user<span class="e">/apop</span>@$B%5!<%PL>(B</tt></p>
+      </blockquote>
+  <hr>
+</dl>
+<p>$B0J>e$N$$$:$l$N>l9g$b!"3HD%%a%$%k%"%I%l%9$r<u?.$7$?$$$H$-$O%f!<%6L>$H(B
+$B$7$F(B user-xxx $B$N$h$&$J3HD%;RIU$NL>A0$r;XDj$7$^$9!#(B</p>
+
+<h2>
+ <a name="forward">$BB>$N%a%$%k%5!<%P$X$NE>Aw(B</a>
+</h2>
+<p>$BK\%5!<%P$KFO$$$?$"$J$?08$N%a%$%k$r!"JL$N%5!<%P$G4IM}$7$F$$$k%a%$%k%"(B
+$B%I%l%9$KE>Aw$9$k>l9g$O!"%[!<%`%G%#%l%/%H%j$K$"$k(B .qmail $B$H$$$&%U%!%$%k$K(B
+$BE>Aw@h$r=q$-$^$9!#(B</p>
+<ol>
+ <li> FTP$B%/%i%$%"%s%H%=%U%H$rMxMQ$7$F$3$N%5!<%P$K%m%0%$%s$9$k(B
+ <li> $B%m%0%$%s8e:G=i$K$D$J$,$k%G%#%l%/%H%j(B($B%U%)%k%@(B)$B$K(B .qmail $B$H$$$&%U%!(B
+      $B%$%k$,$"$k$N$G$3$l$r<j85$N(BPC$B$K%3%T!<$9$k(B
+ <li> $B%a%bD"(B(Notepad.exe)$B$J$IE,Ev$J%F%-%9%H%(%G%#%?$rMxMQ$7$F$3$N%U%!%$(B
+      $B%k$rJT=8$70J2<$N$h$&$K=q$-49$($F%;!<%V$9$k(B
+      <blockquote>
+       <tt>&amp;user2@tensosaki.co.jp</tt>
+      </blockquote>
+      ($B>e5-$NNc$G$O(B <tt>user2@tensosaki.co.jp</tt> $B$,E>Aw@h%"%I%l%9(B)
+ <li> FTP$B%/%i%$%"%s%H%=%U%H$G:FEY(B .qmail $B%U%!%$%k$r%5!<%P>e$KE>Aw$9$k(B
+</ol>
+<p>$BB>%"%I%l%9$KE>Aw$7!"$J$*$+$D$3$N%5!<%P>e$N%a%$%k%\%C%/%9$K$b%a%$%k$r(B
+$B;D$7$?$$>l9g$O(B .qmail $B%U%!%$%k$K85!9$"$C$?(B ./Maildir/ $B$H$$$&9T$r>C$5$:$K(B
+$BE>AwMQ$N9T$rDI2C$7$^$9!#(B</p>
+<blockquote>
+<pre>./Maildir/
+&amp;user2@tensosaki.co.jp</pre>
+</blockquote>
+<h3>
+ $BCm0U(B!
+</h3>
+<p>FTP$B$b(BPOP3$B$HF1MMJ?J8%Q%9%o!<%I$r%M%C%H%o!<%/$KN.$94m81$J$b$N$J$N$G!"(B
+ftp$B@\B3$bFbIt$+$i$NMxMQ$N$_$K@)8B$7$F$$$^$9!#$I$&$7$F$b30It%M%C%H%o!<%/(B
+$B$+$i(BFTP$B$rMxMQ$9$kI,MW$,$"$k>l9g$O4IM}<T$^$G$4AjCL$/$@$5$$!#(B</p>
+
+<hr>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/with-tcpserver/0README	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,13 @@
+
+This directory contains sample files for maintaining ipop3d via daemontools.
+
+
+# make install
+
+Installation directory can be changed by setting DESTDIR.
+eg.
+# make DESTDIR=/other/dir install
+
+Then, edit copied files and change the logging user-id in log/run.
+
+# ln -s /var/qmail/ipopd /service
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/with-tcpserver/Makefile	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,18 @@
+#
+TCPDIR=/usr/local/bin
+TR=${TCPDIR}/tcprules
+DESTDIR	=	/var/qmail/ipopd
+LOGMAIN	=	${DESTDIR}/log/main
+LOGUSER	=	nobody
+
+all: pop.cdb
+
+install:
+	-mkdir -p ${DESTDIR}
+	tar cf - Makefile log run | (cd ${DESTDIR}; tar xpf -)
+	chmod +x ${DESTDIR}/run ${DESTDIR}/log/run
+	mkdir ${LOGMAIN}
+	chown ${LOGUSER} ${LOGMAIN}
+
+pop.cdb:	pop
+	cat $> | ${TR} $@ pop.tmp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/with-tcpserver/log/run	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,5 @@
+#!/bin/sh
+exec env - \
+PATH=/bin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin \
+setuidgid nobody \
+multilog t ./main
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/with-tcpserver/pop	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,3 @@
+127.0.0.:allow,INTRANET=""
+10.0.0.0-127:allow,INTRANET=""
+all:allow
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/APOPtools/with-tcpserver/run	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,5 @@
+#!/bin/sh
+# ipoper should be located in one of the $PATH elements.
+exec env - \
+PATH=/bin:/usr/bin:/usr/sbin:/var/qmail/ipopd:/usr/local/bin:/usr/local/etc \
+tcpserver -HR -c40 -x/var/qmail/ipopd/pop.cdb 0 pop3 ipop3d 2>&1
--- a/Makefile	Mon Sep 14 15:17:45 2009 +0900
+++ b/Makefile	Mon Sep 14 19:23:11 2009 +0900
@@ -252,7 +252,9 @@
 #	British.  As of 2005, the Julian calendar and the Gregorian calendar
 #	diverge by 15 days.
 
-EXTRACFLAGS=
+# EXTRACFLAGS=-DQMAIL -DRESTRICT_POP -DXADDR_DELIM="+" -DDOTQMAIL=".forward"
+## EXTRACFLAGS=-DQMAIL -DRESTRICT_POP
+EXTRACFLAGS=-DQMAIL -DRESTRICT_POP -DINET6
 
 
 # Extra linker flags (additional/alternative libraries, etc.)
@@ -728,6 +730,7 @@
 clean:
 	@echo Removing old processed sources and binaries...
 	$(SH) -c '$(RM) an ua OSTYPE SPECIALS c-client mtest imapd ipopd mailutil mlock dmail tmail || true'
+	$(SH) -c '$(RM) ip6 || true'
 	$(CD) tools;$(MAKE) clean
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.maildir	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,93 @@
+Pine 4.0x Maildir c-client module
+---------------------------------
+
+Written by Mattias Larsson <ml@techno.org> <mta@freeit.com>
+
+This is the second release of my Maildir driver for Pine 4. It is based
+on Eric Greens IMAP2bis Maildir driver.
+
+PLEASE NOTE that this driver has only been tested in the IMAP4rev1 daemon
+before. It was just put into Pine 4.00, and it looks like it works, but it
+has not been extensively tested. It has been running for 8 months in
+production in our IMAP4 daemon though.
+
+PLEASE NOTE:
+
+This driver needs to store the UID's of the message in the file somehow. In
+the earlier versions of this driver this was done by adding a new maildir
+flag (the ,3 flag), however, this solution was not very good since most
+other clients could not handle it. Thus I had to find another solution. In
+this driver I use a pretty radical method. Any file in the maildir with the
+execute bit set has its UID set in the mtime of the file. So you should not
+edit the files in here, or in any otherway update the mtime, because then
+the UID gets changed. Most clients should not do this, so I think this
+solution is compatible with most other clients (if you find one that isn't,
+let me know). If you for some reason have to edit a file in the Maildir,
+delete the ".uidvalidity" file in the root of the Maildir (ie, the dir where
+you find cur/ new/ and tmp/). Alternatively, edit maildir.c and define the
+NO_UID_VALIDITY option, which will cause the Maildir to get set new UID's on
+every start up. Note that if you are running IMAP and Netscape as a client,
+you can't change the UID's, because Netscape do not support the UID validity
+flag in the IMAP protocol. So use this with care. 
+
+Please edit the maildir.c file in any case. There are 3 options you can
+set yourself. The default configuration is not suitable for ISPs. If you are
+an ISP, or system with many users, you might want to consider setting some
+of the options different.
+
+Ohh, if there are problems compiling it, let me know, and please let me know
+what you did to fix it. This thing was developed on Solaris (using both GCC
+and SunCC, should work with both), but I haven't tried it on any other
+platform. It is also known to compile cleanly on Linux RH5.1
+
+CONFIGURATION
+-------------
+
+There are a few configurable options. You find these at the top of the
+maildir.c file (and it can be found in imap/src/osdep/unix if I'm not all
+mistaken). Right now, two options are configurable. By default it is
+configured for ISP use, something that you might want to change if you use
+it at home.
+
+HOW TO USE
+----------
+
+Use it as any other c-client driver. There is some option you want to change
+if you want all folders to be created as Maildirs (and I can't remember what
+the option is from the top of my head). Read the pine documentation.
+
+CHANGES
+-------
+
+Rel 4.  Coredump problem fixed. In release 3 I decided to user the sparep
+	in the message cache so no patching of mail.h would be necessary,
+	however, PINE uses this pointer internally for other things, causing
+	coredumps when used with the Rel 3. patch.
+
+Rel 3.	New way of storing UID's (compatible with ,2 clients).
+	Multiple inbox patches applied
+
+Rel 2.  Pine 4 changes.
+
+Rel 1.  Imap4rev 1 driver
+
+FINAL NOTES
+-----------
+
+I'll try to maintain and release new versions as soon as I have time over,
+which unfortunately does not happen very often in this business ;)
+
+You can (might) find newer versions of this driver at:
+
+http://www.freeit.com/mta/
+
+
+Regards,
+Daniel Mattias Larsson
+
+e-mail: ml@techno.org
+ph: +46-707-268785
+snail-mail:
+Industrivagen 4
+SE-194 77 Upplands Vasby
+SWEDEN
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.qmailapop	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,366 @@
+//
+// qmail+maildir+apop+virtualdomain+POPbeforeSMTP extensions to uw-imapd
+// Japanese Document below
+//
+
+[Comentary]
+This patch kit enables uw-imapd to handle;
+  * maildir
+  * qmail's extended mail addresses of user (~/.qmail-ext)
+  * Postfix's extended mail addresses of user (~/.forward+ext)
+  * Accesses to extended mail addresses (authenticated with ~/.apop-ext)
+  * Virtual domain user switching
+
+Because this package is produced those who want to avail all features above,
+we recommend you to turn on all switches for every extension.
+Please let me recommend you not to use plain POP3 with this package.
+If you want to cling onto POP3, please use qmail-pop3d which comes with
+qmail distribution.
+
+[Configuration]
+You can select these compilation switches.
+
+  Where:	./Makefile
+  Switch:	QMAIL
+  What:		Support maildir and user's address extension.
+  		This switch is requisite.
+  
+  Where:	./Makefile
+  Switch:	INET6
+  What:		Support IPv6 address
+  		WORKS fine only via ucspi-tcp+ipv6patch
+  		If you are using tcpserver-ipv6, set this.
+  
+  Where:	./Makefile
+  Switch:	POSTFIX
+  What:		Defaults user address file to ~/.forward and
+		extension delimiter to "+".
+		Setting this flag on is equavalent to declare
+		-DQMAIL -DDOTQMAIL=".forward" -DXADDR_DELIM="+"
+		in ./Makefile.
+  
+  Where:	./Makefile
+  Switch:	RESTRICT_POP
+  What:		Restrict POP3 access from unsafe network.  Allow
+		normal pop3 access only when environment variable
+		INTRANET is set.  This can be controled by tcpd with
+		/etc/hosts.allow.
+  
+  Where:	./src/osdep/unix/Makefile
+  Switch:	DEFAULTMAILDIR (quoted string)
+  What:		Default users' maildir directory when a user does not
+		have ~/.qmail file.
+		The default value is null.  If null, the default value in
+		osdep/unix/maildir.c("Maildir") will be taken.
+  
+  Where:	./src/osdep/unix/Makefile
+  Switch:	QMAILCONTROL (quoted string)
+  What:		Default qmail/control directory.
+		The default value is "/var/qmail/control"
+  
+  Where:	./src/osdep/unix/Makefile
+  Switch:	USERAPOPFILE (string)
+  What:		User's APOP password file relative to their home dir.
+		".apop" is set by default.
+  		One of recommended values is "Mail/.apop".
+		NOTE THAT USERAPOPFILE should NOT be readable by others.
+		Do chmod 600 USERAPOPFILE.
+  
+  Where:	./src/osdep/unix/Makefile
+  Switch:	APOPOPEN (string)
+  What:		Command name to decode APOP password from USERAPOPFILE
+		"/usr/local/sbin/deapop" is set by default.
+  		NOTE THAT you should install deapop command too.
+		If you don't want to think about this,
+		install the following shell script into /usr/local/sbin/deapop
+
+		  #!/bin/sh
+		  cat "$@"
+
+  Where:	./src/osdep/unix/Makefile
+  Switch:	POPBEFORESMTP
+  What:		Turn on `POP before SMTP' feature.
+  		The next variable POP3RECORDER takes effect when
+		this variable is defined.
+
+  Where:	./src/osdep/unix/Makefile
+  Switch:	POP3RECORDER (string)
+  What:		Command name to achieve `POP before SMTP'.
+		"/usr/local/etc/pop3-record" is set by default.
+  		This recorder program should take one argument of
+		fully qualified hostname (or IP address) where the POP
+		authentication is passed to.
+
+[NO WARRANTY]
+
+	This package  comes from absolutely NO WARRANTY.   The author of
+	this package is  not responsible for any result  caused by using
+	this software.  The  copyright of the extension part  is held by
+	HIROSE, Yuuji [yuuji@gentei.org].
+
+[COPYING]
+
+	You can re-distribute this  package without any cost except some
+	practical cost(magnetical  media or so).   Although this package
+	basically obeys  the license  terms in a  file CPYRIGHT  in this
+	directory,  there is  one exception;  when you  modify  the code
+	against   the  extensional   part  (over   uw-imapd)   and  that
+	modification is a kind of bug-fix, modification should be telled
+	to  the  author of  extensional  part  if  you are  thinking  of
+	re-distribute your modification  to the public.  This limitation
+	is  to aim  to  make this  extensional  package reasonably  safe
+	always in any time.  Please feel free to hack and distribute it!
+
+
+-- Japanese document follows...
+
+【qmail+maildir+APOP用POPサーバ】
+
+	このimapパッケージは、qmailとIMAPを組み合わせて使うこと *ではな
+	く* qmail+maildir+APOPを柔軟に利用しようということを目的として作
+	られましたのでIMAPでのテストは十分に行なわれていません。このパッ
+	ケージは以下のような方を満足させるでしょう。
+
+	* qmailを利用している
+	* mail spool には安全性の高い Maildir 形式を利用し(させ)ている
+	* ~/.qmail-ext ファイルによるqmailの拡張アドレスをよく利用している
+	* virtual domain を活用しまくっている
+
+	上記のようなことができるqmailですが、この機能を使いこなすために
+	はUNIXマシンにログインしてローカルファイルを見に行くメイルリーダ
+	を使うという方法しかありませんでした。これでは不便なので、上記の
+	使い分けを認識するPOPサーバを作ろうということで作成したのがこの
+	パッケージです。またPOPのみのサーバ利用が多い昨今、リモートから
+	の認証にログインパスワードを使わずにメイル専用パスワードを利用さ
+	せる変更も行なっています。これによりPOPもAPOP(POPのパスワード認
+	証の暗号化版)も共通のパスワードを利用できるようにしました。また、
+	POP の場合は既存ユーザのパスワード管理を考えて、認証時にUNIXパス
+	ワードも参照するようにしています。
+
+	もう一点、POPはパスワードをプレインテキストで流すため、外部ネッ
+	トワークからの利用は危険です。そこでPOPの利用を一部のネットワー
+	クに限定する機能もつけました(tcp_wrappersやtcpserverが必要)。
+
+【インストール】
+
+	デフォルト設定では
+
+	* POP3は拒否する
+	* ユーザのパスワード設定ファイルは ~/.apop
+	* ~/.apop のデコードプログラムは /usr/local/sbin/deapop
+
+	となっています。APOP認証はサーバ側で必ず元のパスワードを知る必要
+	があります。これまでのAPOPサーバは全てのユーザ毎に管理者権限でパ
+	スワードを設定する必要がありました。一見安全そうですが、じつはユー
+	ザがパスワードを変更する頻度を限りなくゼロに近づけているだけです。
+	そもそもAPOPはサーバ側で元パスワードを取得する必要があるので必ず
+	復元可能な形で保存されなければなりません。ということはどんなに凝っ
+	た方法で保存しても結局は復号できるのですから、複雑な方法で暗号化
+	&格納をすることは手間を増やすだけです。いずれにしてもroot権限さ
+	えあれば元のパスワードは簡単に読めるわけですから、最初からユーザ
+	自身にパスワード管理をさせてしまっても何ら問題は無く、むしろその
+	方がパスワードをこまめに変えてくれる可能性が(ちょりっと)上がりま
+	す。ただし、誰にでもパスワードが読めては困るので、パスワードファ
+	イルを chmod 600 しておかないとメイルの取り込みが出来ないように
+	なっています。またどうしても平文でファイルに保存するのだけはいや
+	だーという場合のために、APOPパスワードファイルは 
+	/usr/local/sbin/deapop というコマンドを経由して読み込むようになっ
+	ています。これにデコードする処理を書いておきます。もし、とくにエ
+	ンコードしなくてもいいという場合は
+
+	  #!/bin/sh
+	  cat "$@"
+
+	というシェルスクリプトでも入れておいてください。このパスワードは
+	ログインパスワードとは独立しているのでこれで大きな問題は起こらな
+	いでしょう(責任は持ちませんが:-)。
+
+	コンパイル時の変数は上記英文解説の場所を読んでください。
+
+【ユーザから見た使い方】
+
+	まず、~/.qmail に正しくmaildirが設定されていることを確認します。
+	maildirをまだ作っていない場合は、
+	
+	% /var/qmail/bin/maildirmake ~/maildir
+
+	とし、~/.qmail に
+
+	./maildir/
+
+	と書きます。またメイル専用パスワードを ~/.apop に記録します。
+	これは apoppasswd コマンドで行ないます。
+
+	% apoppasswd
+
+	これで完了です。apoppasswdコマンドは APOPtools/apoppasswd にある
+	ので管理者がサイトの環境に手直しした上で一般ユーザのPATHの通る場
+	所にインストールして使って下さい。
+
+	さて、拡張アドレスを使いましょう。ログイン名を login とします。
+	login-isogi@hogehoge.co.jp のようなアドレスは ~/.qmail-isogi とい
+	うファイルで作成できます。login-isogi 用のmaildirを作ります。
+
+	% /var/qmail/bin/maildirmake ~/isogidir
+
+	これを ~/.qmail-isogi に登録します。
+
+	./isogidir/
+
+	最後に login-isogi 用のパスワードを設定します。
+
+	% apoppasswd -e isogi -c
+	Enter APOP Password:
+
+	とすると、maildirの作成とパスワードの設定が同時に行えます。
+	maildirとパスワードの作成が完了したら、利用してるメイルリーダの
+	APOP アカウントの「アカウント名」をlogin-isogi にして接続します。
+
+【POP before SMTPについて】
+
+	まず tcp_wrappers を利用している場合について説明します。
+	tcpserverを利用する場合も原理は同じなので仕組みだけ理解してくだ
+	さい。
+
+	tcp_wrapperとtcp-envを組み合わせてSMTPサーバを中継用に使うドメイ
+	ンを限定して使っていると思います。これの発展形でPOP接続して来た
+	ドメインだけにSMTPサーバを使わせる手法のことを "POP before SMTP" 
+	と呼びます。このパッケージでも APOP 接続をしたドメインに対して
+	SMTPの中継許可を与えることが出来ます。本パッケージの ./APOPtools 
+	ディレクトリにある pop3-* を /usr/local/etc にインストールします。
+	3つのファイルの実体は同じです。さらに以下の作業をします。
+
+	* 原本となる /etc/hosts.allow を /etc/hosts.allow.src にコピー
+	* crontab で10分毎に /usr/local/etc/pop3-age を起動させる
+
+	後者は、大抵のOSの場合 root の crontab に
+
+	     */10  *  *  *  *   root    /usr/local/etc/pop3-age
+
+	などと書けば設定できます。pop3-* スクリプトは自身の環境に合わせ
+	て適宜修正して下さい。この段階で、tcp_wrapper の定義ファイルは 
+	/etc/hosts.allow.src が大元で、/etc/hosts.allow はcronによって自
+	動生成されるものとなります。hosts.allowをいじっても自動的に上書
+	きされてしまうので、設定を変えるときは *必ず hosts.allow.src を
+	編集する* ことに注意して下さい。
+
+	さらにipop3dを起動するときに接続してきたホストが環境変数
+	RELAYCLIENT に入るようにしておきます。/etc/inetd.conf でipop3dを
+	起動するときに tcp_wrapper 経由となることを確認します。
+
+	[/etc/inetd.conf]
+	  pop3 stream tcp nowait root /usr/libexec/tcpd /usr/libexec/ipop3d
+
+	1999年頃以降のPC-UNIXではinetdにデフォルトでtcpdが組み込まれてい
+	ることが多いので、inetd.confにtcpdははさまなくて良いこともありま
+	す。続いて /etc/hosts.allow.src で環境変数の設定が起きるようにし
+	ます。
+
+	[/etc/hosts.allow.src]
+		ipop3d : all : setenv RELAYCLIENT %h
+
+	これで POPサービスを利用しに来たクライアントのアドレスが環境変数
+	に入ります。
+
+	tcpserverの場合は、付属の pop3-record スクリプトの後半に例がある
+	のでそれを利用してください。
+
+	なお、tcp_wrappers 用の pop3-age スクリプトは負荷の高いマシンで
+	は hosts.allow ファイルが空になる可能性があります。lockすれば多
+	少ましになるでしょうが完ぺきではありません。もし、hosts.allowの
+	書き換えに失敗するような負荷の高い環境で使う場合は tcp_wrappers 
+	ではなく、tcpserverでのアクセス制御をすることを強く勧めます。こ
+	ちらはロックの必要もなく、安全にアクセス制御ファイルの更新ができ
+	ます。
+
+【POPアクセス制御について】
+
+	POP3とAPOPは同じポートを使うので「外部からはAPOPだけ許す」などの
+	制御はルータやtcp_wrappersなどだけではできません。このipop3dでは、
+	生のPOP3は環境変数INTRANETが定義されているときだけに利用を制限す
+	ることができます。tcp_wrappers の例を示します。
+
+		ipop3d : localhost .localnet.hoge.jp \
+			: setenv INTRANET : setenv RELAYCLIENT %h
+		ipop3d : all : setenv RELAYCLIENT %h
+
+	としておけば、ローカルネットワーク内だけで生POP3を使うことができ
+	ます。
+
+【virtualdomain機能について】
+
+	qmailでは /var/qmail/control/virtualdomains を使うことで、ユーザ
+	が任意のメイルドメインを持つことができます。これを解釈するように
+	しました。/var/qmail/control/virtualdomain ファイルで
+
+		virtual.hoge.co.jp:user1
+		dokan.hoge.co.jp:user2-dokan
+
+	としておくと、XX@virtual.hoge.co.jp は ~user1/.qmail-XX に配送さ
+	れ、YY@dokan.hoge.co.jp は ~user2/.qmail-dokan-YY に配送されます。
+	それがMaildirスプールを含む場合、本パッケージのIMAP/POPで取り込
+	むことができます。デフォルトではこのためのパスワードはそれぞれ
+
+		~user1/.apop-XX
+		~user2/.apop-dokan-YY
+
+	ファイルに保存しておかなければなりません。
+
+【Postfixの拡張アドレス対応について】
+
+	Postfixによる ~/.forward+ext で発生する拡張アドレスは、その配送
+	先がMaildirであれば本パッケージでも利用できます。Postfix のデフォ
+	ルト設定の
+		forward_path = $home/.forward$recipient_delimiter$extension,
+			     $home/.forward
+		recipient_delimiter = +
+
+	のまま Postfix を動かしている場合はトップレベルのMakefileの
+	EXTRACFLAGS に -DPOSTFIX を追加して下さい(-DQMAILも必要です)。こ
+	れにより、拡張アドレスを決めるファイルが ".forward" に、拡張部分
+	を区切る文字列が "+" になります。いずれかを変更している場合はた
+	とえば、
+
+		-DDOTQMAIL=".postfix" -DXADDR_DELIM="-"
+
+	のように変更できます。もし、Postfix の .forward+ext を利用する場
+	合は周辺ツールの APOPtools/apoppasswd, APOPtools/apopcall.c の対
+	応する変数も変更する必要があることに注意して下さい。また、パスワー
+	ドファイルも ~/.apop-ext ではなく~ /.apop+ext となることに注意が
+	必要です。これらが面倒な場合は、Postfix の設定の方で .qmail-ext 
+	を見るようにしてしまうのも手です。この場合は
+
+		recipient_delimiter = -
+		forward_path = $home/.forward$recipient_delimiter$extension,
+				$home/.qmail$recipient_delimiter$extension,
+				$home/.forward
+
+	とすると ~/.qmail-ext も参照するようになり、デフォルト状態の本パッ
+	ケージのまま利用することができるでしょう。
+
+【Postfixの POP before SMTPについて】
+
+	main.cf で たとえば次のようにします。
+
+		smtpd_recipient_restrictions = 
+			permit_mynetworks
+			check_client_access hash:/etc/postfix/client_access
+
+	ここで /etc/postfix/client_access は POP before SMTP の許可ホス
+	トリストを保持するためのファイル名で、既に使われてはいないものに
+	します。配布ディレクトリの APOPtools/pop3-record.postfix は
+	/etc/postfix/client_access ファイルをリレー許可判定に使うことを
+	前提とした Postfix 用のスクリプトです。
+
+【謝辞】
+
+	安井卓さん(tach@debian.or.jp)にはsyslog関係のパッチを頂きました。
+	ここに感謝の意を表します。
+
+【免責】
+
+	IMAPパッケージに本ドキュメントで説明した拡張機能を追加する部分の
+	著作権は広瀬雄二[yuuji@gentei.org]が保持します。このプログラムを
+	用いて生じた如何なる結果に対しても著作権者は責任を負いません。
+
+						2009/9/14 yuuji@gentei.org
--- a/src/c-client/auth_log.c	Mon Sep 14 15:17:45 2009 +0900
+++ b/src/c-client/auth_log.c	Mon Sep 14 19:23:11 2009 +0900
@@ -105,6 +105,10 @@
   char *ret = NIL;
   char *user,*pass,*authuser;
   if (user = (*responder) (PWD_USER,sizeof (PWD_USER),NIL)) {
+#ifdef QMAIL
+    extern char* conv_virtualdomain(char*);
+    user = conv_virtualdomain(user);
+#endif
     if (pass = (*responder) (PWD_PWD,sizeof (PWD_PWD),NIL)) {
 				/* delimit user from possible admin */
       if (authuser = strchr (user,'*')) *authuser++ = '\0';
--- a/src/c-client/auth_md5.c	Mon Sep 14 15:17:45 2009 +0900
+++ b/src/c-client/auth_md5.c	Mon Sep 14 19:23:11 2009 +0900
@@ -75,9 +75,11 @@
 
 long auth_md5_valid (void)
 {
+#ifndef QMAIL			/* qmail extension can always handle MD5 */
   struct stat sbuf;
 				/* server forbids MD5 if no MD5 enable file */
   if (stat (MD5ENABLE,&sbuf)) auth_md5.server = NIL;
+#endif
   return T;			/* MD5 is otherwise valid */
 }
 
@@ -186,6 +188,7 @@
 char *auth_md5_pwd (char *user)
 {
   struct stat sbuf;
+#ifndef QMAIL
   int fd = open (MD5ENABLE,O_RDONLY,NIL);
   unsigned char *s,*t,*buf,*lusr,*lret;
   char *r;
@@ -214,6 +217,77 @@
     fs_give ((void **) &buf);	/* flush the buffer */
     close (fd);			/* don't need file any longer */
   }
+#else
+# ifndef USERAPOPFILE
+#  define USERAPOPFILE ".apop" 
+# endif
+# ifndef XADDR_DELIM
+#  ifdef POSTFIX		/* Same if-condition is in maildir.c.. sorry */
+#   define XADDR_DELIM "+"
+#  else
+#   define XADDR_DELIM "-"
+#  endif
+# endif
+  extern char *myMailSuffix;
+  char mycrypt[BUFSIZ+1];
+  char *ret = NIL, *tmp=NIL;
+  FILE *apopfile = NIL;
+  struct passwd *pw = getpwnam(user);
+  if (!pw) pw = getpwnam(lcase(tmp=cpystr(user)));
+  if (!pw && strstr(user, XADDR_DELIM)) { /* Check qmail alias */
+    char tmp[BUFSIZ];
+    char *s = user;
+    memset(tmp, 0, BUFSIZ);
+    while (*s && s && !pw) {
+      s = strstr(s, XADDR_DELIM);
+      if (!s) break;
+      strncpy(tmp, user, s-user);
+      s++;
+      pw = getpwnam(tmp);
+    }
+    if (pw) {
+      myMailSuffix = lcase(cpystr(s-1));
+      user[strlen(tmp)] = '\0'; /* zap suffix */
+    }
+  }
+  if (pw) {
+    snprintf(mycrypt, BUFSIZ, "%s/%s", pw->pw_dir, USERAPOPFILE);
+    if (NIL != myMailSuffix) strcat(mycrypt, myMailSuffix);
+    if (stat(mycrypt, &sbuf) < 0) {
+      /* printf("Cannot stat [%s]\015\n", mycrypt); */
+      return ret;
+    }
+    if (sbuf.st_mode & ~(S_IFREG | S_IREAD | S_IWRITE)) {
+      /* printf("Your apoppassword file is readable by others. Do chmod 600 %s%c\n", mycrypt, 015); */
+      return ret;
+    }
+#ifdef APOPOPEN
+    if (stat(APOPOPEN, &sbuf) >= 0) {	/* if APPOPEN exists */
+      /* read apop password via APOPOPEN program */
+      int bytes = 3+strlen(APOPOPEN)+strlen(mycrypt);
+      char *aproc = (char*) fs_get(bytes);
+      snprintf(aproc, bytes, "%s %s%c", APOPOPEN, mycrypt, '\0');
+      apopfile = popen(aproc, "r");
+      memset(aproc, 0, bytes);
+      fs_give((void**)&aproc);
+    }
+#endif /* APOPOPEN */
+    if ((NIL!=apopfile) || (apopfile = fopen( mycrypt, "r" ))) {
+      fgets(mycrypt, sizeof(mycrypt) - 1, apopfile);
+      fclose(apopfile);
+      if (mycrypt[0]) {
+	char p = strlen(mycrypt);
+	while (p > 0 && (mycrypt[p-1] == '\n' || mycrypt[p-1] == '\r')) {
+	   mycrypt[--p] = '\0'; /* zap trailing newlines */
+	}
+      }
+    } else {
+      return ret;
+    }
+    ret = cpystr(mycrypt);
+    memset(mycrypt, 0, sizeof(mycrypt));
+  }
+#endif				/* if QMAIL */
   return ret;			/* return password */
 }
 
@@ -231,6 +305,9 @@
   int i,j;
   char *ret = NIL;
   char *s,*authuser,tmp[MAILTMPLEN];
+#ifdef QMAIL
+  char *userback = cpystr(user);
+#endif
   unsigned char digest[MD5DIGLEN];
   MD5CONTEXT ctx;
   char *hex = "0123456789abcdef";
@@ -260,7 +337,15 @@
     memset (tmp,0,MAILTMPLEN);	/* erase sensitive information */
   }
   if (!ret) sleep (3);		/* slow down possible cracker */
+  else {
+    extern void permitsmtp();
+    /* permitsmtp();*/
+  }
+#ifdef QMAIL
+  return (ret) ? userback : ret;
+#else
   return ret;
+#endif
 }
 
 /*
--- a/src/c-client/mail.c	Mon Sep 14 15:17:45 2009 +0900
+++ b/src/c-client/mail.c	Mon Sep 14 19:23:11 2009 +0900
@@ -6081,6 +6081,9 @@
     if (auth->server && !compare_cstring (auth->name,mechanism))
       return (!(auth->flags & AU_DISABLE) &&
 	      ((auth->flags & AU_SECURE) ||
+#ifdef QMAIL
+	       getenv("INTRANET") ||
+#endif
 	       !mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL))) ?
 	(*auth->server) (resp,argc,argv) : NIL;
   return NIL;			/* no authenticator found */
--- a/src/c-client/mail.h	Mon Sep 14 15:17:45 2009 +0900
+++ b/src/c-client/mail.h	Mon Sep 14 19:23:11 2009 +0900
@@ -858,6 +858,7 @@
   unsigned int spare7 : 1;	/* seventh spare bit */
   unsigned int spare8 : 1;	/* eighth spare bit */
   void *sparep;			/* spare pointer */
+  void *maildirp;		/* for the Maildir driver */
   unsigned long user_flags;	/* user-assignable flags */
 } MESSAGECACHE;
 
--- a/src/imapd/imapd.c	Mon Sep 14 15:17:45 2009 +0900
+++ b/src/imapd/imapd.c	Mon Sep 14 19:23:11 2009 +0900
@@ -553,6 +553,9 @@
 
 				/* plaintext login with password */
 	else if (!strcmp (cmd,"LOGIN")) {
+          #ifdef QMAIL
+          extern char* conv_virtualdomain(char*);
+          #endif
 	  if (user) fs_give ((void **) &user);
 	  if (pass) fs_give ((void **) &pass);
 				/* two arguments */
@@ -573,7 +576,11 @@
 	  else {		/* delimit user from possible admin */
 	    if (s = strchr (user,'*')) *s++ ='\0';
 				/* see if username and password are OK */
+#ifdef QMAIL
+	    if (server_login (conv_virtualdomain(user),pass,s,argc,argv)) {
+#else
 	    if (server_login (user,pass,s,argc,argv)) {
+#endif
 	      state = SELECT;	/* make select */
 	      alerttime = 0;	/* force alert */
 	      response = logwin;/* return logged-in capabilities */
--- a/src/ipopd/ipop3d.c	Mon Sep 14 15:17:45 2009 +0900
+++ b/src/ipopd/ipop3d.c	Mon Sep 14 19:23:11 2009 +0900
@@ -96,6 +96,9 @@
 void trmint ();
 int pass_login (char *t,int argc,char *argv[]);
 char *apop_login (char *chal,char *user,char *md5,int argc,char *argv[]);
+#ifdef QMAIL
+char* conv_virtualdomain(char *account);
+#endif
 char *responder (void *challenge,unsigned long clen,unsigned long *rlen);
 int mbxopen (char *mailbox);
 long blat (char *text,long lines,unsigned long size,STRING *st);
@@ -128,7 +131,11 @@
     AUTHENTICATOR *auth = mail_lookup_auth (1);
     while (auth && compare_cstring (auth->name,"CRAM-MD5")) auth = auth->next;
 				/* build challenge -- less than 128 chars */
+#ifndef QMAIL
+    if (!(auth->flags & AU_DISABLE))
+#else
     if (auth && auth->server && !(auth->flags & AU_DISABLE))
+#endif
       sprintf (challenge,"<%lx.%lx@%.64s>",(unsigned long) getpid (),
 	       (unsigned long) time (0),tcp_serverhost ());
     else challenge[0] = '\0';	/* no MD5 authentication */
@@ -258,10 +265,17 @@
 				/* get user name */
 	    if (!(t && *t && (s = strtok (t," ")) && (t = strtok(NIL,"\012"))))
 	      PSOUT ("-ERR Missing APOP argument\015\012");
-	    else if (!(user = apop_login (challenge,s,t,argc,argv)))
-	      PSOUT ("-ERR Bad APOP\015\012");
-	    else if ((state = mbxopen ("INBOX")) == TRANSACTION)
-	      syslog (LOG_INFO,"APOP user=%.80s host=%.80s nmsgs=%lu/%lu",
+ #ifdef QMAIL
+	    else if (!(user = apop_login (challenge,conv_virtualdomain(s),t,argc,argv))) {
+ #else /* !QMAIL */
+	      else if (!(user = apop_login (challenge,s,t,argc,argv))) {
+ #endif /* QMAIL */
+	      PSOUT ("-ERR Bad APOP (Maybe your password is expired)\015\012");
+	      user = cpystr (s);
+              syslog (LOG_INFO,"APOP login failure user=%.80s host=%.80s",
+                    user,tcp_clienthost ());
+	    } else if ((state = mbxopen ("INBOX")) == TRANSACTION)
+	      syslog (LOG_INFO,"APOP user=%.80s host=%.80s nmsgs=%ld/%ld",
 		      user,tcp_clienthost (),nmsgs,stream->nmsgs);
 	    else syslog (LOG_INFO,"APOP user=%.80s host=%.80s no mailbox",
 			 user,tcp_clienthost ());
@@ -279,8 +293,20 @@
 	  }
 	  else PSOUT ("+OK STLS completed\015\012");
 	}
+#ifndef RESTRICT_POP
 	else if (!mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL) &&
 		 !strcmp (s,"USER")) {
+#else	/* !RESTRICT_POP */
+	else if (!strcmp (s,"USER")) {
+	  if (getenv("INTRANET") == NIL) {
+	    PSOUT("-ERR Sorry, we don't allow POP3 from your network.  Use APOP instead.\015\012");
+	    user = cpystr(t);
+	    syslog (LOG_INFO,"Plain POP3 is restricted user=%.80s host=%.80s",
+		    user,tcp_clienthost ());
+	    memset(user, '\0', strlen(user));
+	    break;
+	  }
+#endif
 	  if (host) fs_give ((void **) &host);
 	  if (user) fs_give ((void **) &user);
 	  if (pass) fs_give ((void **) &pass);
@@ -294,7 +320,11 @@
 	      user = cpystr (s);/* copy user name */
 	    }
 				/* local user name */
+#ifdef QMAIL
+	    else user = conv_virtualdomain(cpystr (t));
+#else
 	    else user = cpystr (t);
+#endif
 	    PSOUT ("+OK User name accepted, password please\015\012");
 	  }
 	  else PSOUT ("-ERR Missing username argument\015\012");
--- a/src/osdep/unix/Makefile	Mon Sep 14 15:17:45 2009 +0900
+++ b/src/osdep/unix/Makefile	Mon Sep 14 19:23:11 2009 +0900
@@ -27,7 +27,7 @@
 # Command line build parameters
 
 EXTRAAUTHENTICATORS=
-EXTRADRIVERS=mbox
+EXTRADRIVERS=maildir mbox
 PASSWDTYPE=std
 SSLTYPE=nopwd
 IP=4
@@ -102,6 +102,7 @@
 NEWSSPOOL=$(SPOOLDIR)/news
 RSHPATH=/usr/ucb/rsh
 MD5PWD=/etc/cram-md5.pwd
+MD5CFLAGS= -DAPOPOPEN=\"/usr/local/sbin/deapop\" -DUSERAPOPFILE=\".apop\" -DPOPBEFORESMTP -DPOP3RECORDER=\"/usr/local/etc/pop3-record\"
 # Tries one of the test alternatives below if not specified.
 LOCKPGM=
 # Test alternatives if LOCKPGM not specified
@@ -144,17 +145,21 @@
 # However, mh needs to be before any sysinbox formats (such as mmdf or unix)
 # since otherwise INBOX won't work correctly when mh_allow_inbox is set.
 #
-DEFAULTDRIVERS=imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile
+DEFAULTDRIVERS=maildir imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile
 CHUNKSIZE=65536
 
 # Normally no need to change any of these
+EXTRACFLAGS=-DQMAIL
+# Next variable controls default maildir when user has no ~/.qmail
+#MAILDIRCFLAGS=-DDEFAULTMAILDIR="maildir" -DQMAILCONTROL="/var/qmail/control"
+MAILDIRCFLAGS=-DQMAILCONTROL="/var/qmail/control"
 
 ARCHIVE=c-client.a
 BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o utf8aux.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 mix.o
-CFLAGS=-g
+ unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o mix.o maildir.o
+CFLAGS=-g $(EXTRACFLAGS)
 
 CAT=cat
 MAKE=make
@@ -892,6 +897,7 @@
 unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h
 utf8.o: mail.h misc.h osdep.h utf8.h tmap.c widths.c
 utf8aux.o: mail.h misc.h osdep.h utf8.h
+maildir.o: mail.h misc.h osdep.h maildir.h dummy.h
 
 
 # OS-dependent
@@ -960,6 +966,7 @@
 	@echo Once-only environment setup...
 	echo $(CC) > CCTYPE
 	echo $(BASECFLAGS) '$(EXTRACFLAGS)' -DCHUNKSIZE=$(CHUNKSIZE) > CFLAGS
+	echo '$(MAILDIRCFLAGS)' >> CFLAGS
 	echo -DCREATEPROTO=$(CREATEPROTO) -DEMPTYPROTO=$(EMPTYPROTO) \
 	 -DMD5ENABLE=\"$(MD5PWD)\" -DMAILSPOOL=\"$(MAILSPOOL)\" \
 	 -DANONYMOUSHOME=\"$(MAILSPOOL)/anonymous\" \
@@ -967,6 +974,7 @@
 	 -DRSHPATH=\"$(RSHPATH)\" -DLOCKPGM=\"$(LOCKPGM)\" \
 	 -DLOCKPGM1=\"$(LOCKPGM1)\" -DLOCKPGM2=\"$(LOCKPGM2)\" \
 	 -DLOCKPGM3=\"$(LOCKPGM3)\" > OSCFLAGS
+	echo $(MD5CFLAGS) >> OSCFLAGS
 	echo $(BASELDFLAGS) $(EXTRALDFLAGS) > LDFLAGS
 	echo "$(ARRC) $(ARCHIVE) $(BINARIES);$(RANLIB) $(ARCHIVE)" > ARCHIVE
 	echo $(OS) > OSTYPE
--- a/src/osdep/unix/env_unix.c	Mon Sep 14 15:17:45 2009 +0900
+++ b/src/osdep/unix/env_unix.c	Mon Sep 14 19:23:11 2009 +0900
@@ -422,6 +422,10 @@
   case SET_DISABLEPLAINTEXT:
     disablePlaintext = (long) value;
   case GET_DISABLEPLAINTEXT:
+#ifdef RESTRICT_POP
+    if (getenv("INTRANET") == NIL) disablePlaintext = 1;
+    else disablePlaintext = NIL;
+#endif
     ret = (void *) disablePlaintext;
     break;
   case SET_CHROOTSERVER:
@@ -665,6 +669,7 @@
   char *s;
   struct passwd *pw;
   struct passwd *ret = NIL;
+#ifndef QMAIL	/* imapext md5 checker run previously. no need to do here */
   if (auth_md5.server) {	/* using CRAM-MD5 authentication? */
     if (s = auth_md5_pwd (user)) {
       if (!strcmp (s,pwd) || ((*pwd == ' ') && pwd[1] && !strcmp (s,pwd+1)))
@@ -673,7 +678,9 @@
       fs_give ((void **) &s);
     }
   }
-  else if (pw = pwuser (user)) {/* can get user? */
+  else
+#endif
+  if (pw = pwuser (user)) {/* can get user? */
     s = cpystr (pw->pw_name);	/* copy returned name in case we need it */
     if (*pwd && !(ret = checkpw (pw,pwd,argc,argv)) &&
 	(*pwd == ' ') && pwd[1] && (ret = pwuser (s)))
@@ -697,6 +704,10 @@
   struct passwd *pw = NIL;
   int level = LOG_NOTICE;
   char *err = "failed";
+#ifdef QMAIL
+  char usr[MAILTMPLEN], *apoppswd;
+  strncpy(usr, user, MAILTMPLEN-1);
+#endif
 				/* cretins still haven't given up */
   if ((strlen (user) >= NETMAXUSER) ||
       (authuser && (strlen (authuser) >= NETMAXUSER))) {
@@ -706,6 +717,16 @@
   }
   else if (logtry-- <= 0) err = "excessive login failures";
   else if (disablePlaintext) err = "disabled";
+#ifdef QMAIL
+  else if ((logtry > 0) &&
+            (apoppswd = auth_md5_pwd(usr))
+           && !strcmp(apoppswd, pwd)
+           && (pw = getpwnam(usr))) {
+    memset(apoppswd, 0, strlen(apoppswd));
+    fs_give((void**) &apoppswd);
+    return pw_login(pw, usr, pw->pw_name, pw->pw_dir, argc, argv);
+  }
+#endif
   else if (!(authuser && *authuser)) pw = valpwd (user,pwd,argc,argv);
   else if (valpwd (authuser,pwd,argc,argv)) pw = pwuser (user);
   if (pw && pw_login (pw,authuser,pw->pw_name,NIL,argc,argv)) return T;
@@ -728,6 +749,34 @@
   return pw_login (pwuser (user),authuser,user,NIL,argc,argv);
 }
 
+void permitsmtp()	/* to update tcp permission */
+{
+#ifdef POPBEFORESMTP
+  #include <sys/types.h>
+  #include <sys/wait.h>
+  #ifndef POP3RECORDER
+  # define POP3RECORDER "/usr/local/etc/pop3-record"
+  #endif
+  int child;
+  int wstat;
+  char *permsmtp = POP3RECORDER;
+
+  switch(child = fork())
+   {
+    case -1:
+	syslog (LOG_INFO,"Cannot exec %s", permsmtp);
+	_exit(111);
+	break;
+    case 0:
+	execl(permsmtp, permsmtp, 0);
+	syslog (LOG_INFO,"Cannot exec %s", permsmtp);
+	_exit(111); break;
+   }
+  waitpid(child, &wstat, 0);
+#endif
+}
+
+
 
 /* Log in as anonymous daemon
  * Accepts: argument count
@@ -781,8 +830,14 @@
       else fatal ("Login failed after chroot");
     }
 				/* normal login */
+#ifdef QMAIL
+    else if (((pw->pw_uid == geteuid ()) || (permitsmtp(), loginpw (pw,argc,argv
+))) &&
+             (ret = env_init (user,home))) chdir (myhomedir ());
+#else
     else if (((pw->pw_uid == geteuid ()) || loginpw (pw,argc,argv)) &&
-	     (ret = env_init (user,home))) chdir (myhomedir ());
+             (ret = env_init (user,home))) chdir (myhomedir ());
+#endif
     fs_give ((void **) &home);	/* clean up */
     if (user) fs_give ((void **) &user);
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/osdep/unix/maildir.c	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,1541 @@
+/*
+ * Maildir Module for PINE 4.0x - fourth release, use with CARE! 
+ *
+ * Author:      Mattias Larsson <ml@techno.org>
+ *
+ * Version:     21.07.98
+ *
+ * Please read the README.maildir file before using this module!
+ *
+ * If you have any questions, please e-mail ml@techno.org 
+ *
+ * Multiple inboxes patch by Dean Gaudet <dgaudet@arctic.org>
+ *
+ * =================================================
+ *
+ * Based on the IMAP2 maildir routines by:
+ *
+ * Author:      Eric Green
+ *              Bloodhounds International Inc.
+ *              thrytis@imaxx.net
+ *
+ * Additional contributions from:
+ *              Aidas Kasparas (kaspar@soften.ktu.lt)
+ *
+ * Date:        27 April 1997
+ * Last Edited: 13 June 1997
+ *
+ * Based (heavily) on mh.c and other c-client library files by Mark Crispin:
+ *
+ *              Mark Crispin
+ *              Networks and Distributed Computing
+ *              Computing & Communications
+ *              University of Washington
+ *              Administration Building, AG-44
+ *              Seattle, WA  98195
+ *              Internet: MRC@CAC.Washington.EDU
+ *
+ * Copyright 1995 by the University of Washington
+ *
+ *  Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appears in all copies and that both the
+ * above copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the University of Washington not be
+ * used in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  This software is made
+ * available "as is", and
+ * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
+ * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
+ * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
+ * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/* CONFIGURABLE OPTIONS - PLEASE CHECK THESE OUT */
+
+#define NO_MAILDIR_FIDDLE	/* disallow Maildir with Maildir in the
+				name. This is useful in an ISP setup
+				using the IMAP daemon. #undef it if you
+				are running a normal pine and know what
+				you are doing */
+
+/* #define NO_ABSOLUTE_PATHS	/* if you define this, all paths
+				use your HOMEDIR is the root instead
+				of the actual root of the machine. This
+				is also useful in an ISP setup with
+				IMAP */
+
+#undef NO_UID_VALIDITIY		/* define this if you want the UID's not
+				to be persistent over sessions. Use this
+				if you use another client to read the
+				maildir that screws up the special way
+				in which we store UIDs. Do not enable
+				unless you are sure you need it. */
+	
+/* END CONFIGURATION */
+
+#define MTA_DEBUG	/* debugging sent to stdout */
+#undef MTA_DEBUG
+
+#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 <sys/types.h>
+#include <dirent.h>
+#include <utime.h>
+#include "maildir.h"
+#include "misc.h"
+#include "dummy.h"
+
+/* Driver dispatch used by MAIL */
+
+DRIVER maildirdriver = {
+  "maildir",			/* driver name */
+				/* driver flags */
+  DR_MAIL|DR_LOCAL|DR_NOFAST|DR_NAMESPACE,
+  (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 */
+  NIL,				/* status of mailbox */
+  maildir_open,			/* open mailbox */
+  maildir_close,		/* close mailbox */
+  maildir_fast,			/* fetch message "fast" attributes */
+  NIL,				/* fetch message flags */
+  NIL,				/* fetch overview */
+  NIL,				/* fetch message envelopes */
+  maildir_fetchheader,		/* fetch message header */
+  maildir_fetchtext,		/* 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 */
+  maildir_gc				/* garbage collect stream */
+};
+
+				/* prototype stream */
+MAILSTREAM maildirproto = {&maildirdriver};
+
+/* Check validity of mailbox
+ */
+ 
+DRIVER *maildir_valid (char *name)
+{
+  return maildir_isvalid(name,T) ? &maildirdriver : NIL;
+}
+
+int maildir_isvalid (char *name,long justname)
+{
+  char tmp[MAILTMPLEN];
+  struct stat sbuf;
+  
+  if (!name || (!*name) || 
+      ((*name == '#') && 
+       (*(name+1) == 0 ||
+	(*(name+1) != 'm' && *(name+1) != 'M') ||
+	(*(name+2) != 'd' && *(name+1) != 'D') ||
+	*(name+3) != '/')) || (*name == '.'))
+    return NIL;
+  
+  /* okay, anything containing the name Maildir will be ignored
+     this is to prevent anyone from fiddling with their incoming Maildir
+     directly, it should be accessed via the INBOX alias */
+
+  #ifdef NO_MAILDIR_FIDDLE
+  if (strstr(name, "Maildir")) {
+	return NIL; 
+	}
+  #endif
+ 				/* If we are requested only to check 
+  				   if the name is appropriate then we
+  				   have done! */
+  if (justname && *name == '#') return T;
+  
+
+				/* must be valid local mailbox */
+  if ((*name != '*') && (*name != '{') &&
+      maildir_file (tmp,name) &&
+				/* assume its maildir if its a dir */
+      stat (tmp,&sbuf) == 0 && S_ISDIR (sbuf.st_mode))
+    return T;
+
+				/* INBOX is for default Maildir */
+  if (!strcmp (ucase (strncpy (tmp,name,MAILTMPLEN)), "INBOX") &&
+      (stat (maildir_file (tmp,name),&sbuf) == 0) &&
+      S_ISDIR (sbuf.st_mode))
+    return T;
+
+  return NIL;
+}
+#ifdef QMAIL
+#ifndef QMAILCONTROL
+# define QMAILCONTROL "/var/qmail/control"
+#endif
+#ifndef DOTQMAIL
+# ifdef POSTFIX
+#  define DOTQMAIL ".forward"
+# else
+#  define DOTQMAIL ".qmail"
+# endif
+#endif
+#ifndef XADDR_DELIM
+# ifdef POSTFIX
+#  define XADDR_DELIM "+"
+# else
+#  define XADDR_DELIM "-"
+# endif
+#endif
+
+/* Convert virtual domain user
+ */
+char* conv_virtualdomain(char *account) {
+  char *dom = strchr(account, '@'), *p;
+  char vd[MAILTMPLEN+1], rewrite[MAILTMPLEN+1], previous[MAILTMPLEN+1];
+  FILE *vdfd;
+  int match=0;
+  snprintf(vd, MAILTMPLEN, "%s/%s", QMAILCONTROL, "virtualdomains");
+  if (NIL == dom) return account;
+  dom++;		/* set position of domain part beginning */
+  if (dom && NIL != (vdfd = fopen (vd, "r"))) {
+    char buf[MAILTMPLEN+1], *s;
+    int l = strlen(dom);
+    int L = strlen(account);
+    while ((s=fgets(buf, MAILTMPLEN, vdfd))) {
+      if (p=strchr(s, '#'))
+        *p = '\0';			/* zap comments */
+      if (!strchr(buf, ':'))
+        continue;
+      while (s && (strrchr(s, '\n') || strrchr(s, '\r') || strrchr(s, ' ')))
+        s[strlen(s)-1] = '\0';
+      if (!strncmp(account, s, L) && s[L] == ':' && s[L+1]) { /* user matches */
+	match = 3;
+        snprintf(rewrite, MAILTMPLEN, "%s%s%s", s+L+1, XADDR_DELIM, account);
+	break;
+      }
+      if (!strncmp(dom, s, l) && s[l] == ':' && s[l+1]) { /* domain matches */
+        match = 2;
+	snprintf(rewrite, MAILTMPLEN, "%s%s%s", s+l+1, XADDR_DELIM, account);
+	continue;
+      }
+      if (match < 2 && s[0] == '.') { /* if domain described in wildcard */
+        if (p=strchr(s, ':')) {
+	  *p = '\0';
+	  if (!strcmp(dom+(strlen(dom)-strlen(s)), s)) {
+	    if (match == 0
+	        || strlen(previous) < strlen(s)) {
+	      match = 1;
+	      strncpy(previous, s, MAILTMPLEN);
+	      snprintf(rewrite, MAILTMPLEN, "%s%s%s", p+1, XADDR_DELIM, account);
+	    }
+	  }
+	}
+      }
+    }
+    fclose(vdfd);
+    if (match) {
+      p = strchr(rewrite, '@');
+      /* fprintf(stderr, "m=%d, rwr=[%s]\n", match, rewrite); */
+      if (p) {
+        *p = '\0';
+      }
+      /* fprintf(stderr, "rwr=[%s]\n", rewrite); */
+      s = cpystr(rewrite);
+      memset(vd, 0, sizeof(vd));
+      memset(rewrite, 0, sizeof(rewrite));
+      memset(previous, 0, sizeof(previous));
+      return s;
+    }
+  }
+  return account; /* return itself */
+}
+/* -------------------------------------------------
+   Qmail virtual domain hack ends
+   ------------------------------------------------- */
+#endif
+
+char *maildir_getmaildir() {
+  static char dir[MAILTMPLEN];
+  extern char *mymailsuffix();
+  static char qfile[MAILTMPLEN];
+  FILE *qmail;
+  dir[0] = '\0';
+  snprintf(qfile, MAILTMPLEN, "%s/%s", myhomedir(), DOTQMAIL);
+  strncat(qfile, mymailsuffix(), MAILTMPLEN);
+  qmail = fopen(qfile, "r");
+  if (NULL != qmail) {	/* if ~/.qmail file exists */
+    char buf[MAILTMPLEN], *s;
+    while ((s=fgets(buf, MAILTMPLEN, qmail))) {
+	/* Skip preceding spaces and trailing newlines */
+	while (*s && (*s == ' ' || *s == '\t')) {s++;}
+	while (*s && (s[strlen(s)-1] == '\r' || s[strlen(s)-1] == '\n')) {
+	s[strlen(s)-1] = '\0';
+	}
+	if (*s == '#') continue;
+	if (s[strlen(s)-1] != '/') continue; /* Skip non maildir format */
+        if (*s == '~' && *(s+1) == '/')
+            *s = '.';           /* Convert `~/' to `./' (for Postfix) */
+	strncpy(dir, s, MAILTMPLEN);
+        break;
+    }
+    fclose(qmail);
+  }
+#ifdef DEFAULTMAILDIR
+  else {
+    strncpy(dir, DEFAULTMAILDIR, MAILTMPLEN);
+  }
+#endif
+  if (dir[0]) {
+    return dir;
+  } else {
+#ifdef DEFAULTMAILDIR
+    snprintf(dir, MAILTMPLEN, "%s/%s/", myhomedir(), DEFAULTMAILDIR);
+#else
+    snprintf(dir, MAILTMPLEN, "%s/%s/", myhomedir(), MAILDIRPATH);
+#endif
+    return dir;
+  }
+}
+
+/* Maildir mail generate file string
+ */
+
+char *maildir_file (char *dst,char *name)
+{
+  char tmp[MAILTMPLEN];
+  
+  if (strlen (name) > 3 &&	/* safe do other comparisons */
+      (*name == '#') &&
+      (name[1] == 'm' || name[1] == 'M') &&
+      (name[2] == 'd' || name[2] == 'D') &&
+      (name[3] == '/'))
+    name += 4;
+
+#ifdef NO_ABSOLUTE_PATHS  
+  if (*name == '/') {	
+  /* we do not want to accept / absolute paths, so lets strip the first
+     / ... */
+    snprintf(dst, MAILTMPLEN, "%s/%s/cur", myhomedir(), name+1);
+
+/*    strncpy (dst, name, MAILTMPLEN - 2);
+    strncat (dst, "/cur", MAILTMPLEN - 2);
+    dst[MAILTMPLEN - 1] = '\0'; */
+  }
+  else
+    snprintf (dst, MAILTMPLEN, "%s/%s/cur",myhomedir (),
+	    strcmp (ucase (strcnpy (tmp, name, MAILTMPLEN)), "INBOX") ? name : maildir_getmaildir());
+#else
+  if (*name == '/') {	
+    strncpy (dst, name, MAILTMPLEN - 2);
+    strncat (dst, "/cur", MAILTMPLEN - 2);
+    dst[MAILTMPLEN - 1] = '\0';
+  }
+  else {
+      char *maildir = maildir_getmaildir();
+      if (*maildir == '/') {
+          snprintf (dst,MAILTMPLEN,"%scur",maildir);
+      } else {
+          snprintf (dst,MAILTMPLEN,"%s/%s/cur",myhomedir (),
+                   strcmp (ucase (strncpy (tmp, name, MAILTMPLEN)), "INBOX") ? name : maildir);
+      }
+  }
+
+#endif 
+  
+  #ifdef MTA_DEBUG
+  printf("maildir_file '%s'\n", dst);
+  #endif
+  return dst;
+}
+
+/* Maildir open
+ */
+ 
+MAILSTREAM *maildir_open (MAILSTREAM *stream)
+{
+ char tmp[MAILTMPLEN],tmp2[MAILTMPLEN];
+
+ if (!stream) return &maildirproto;
+ if (LOCAL) {		/* recycle stream */
+	maildir_close (stream, 0);
+	stream->dtb = &maildirdriver;
+	mail_free_cache (stream);
+	stream->uid_last = 0;       /* default UID validity */
+	stream->uid_validity = time (0);
+	}
+
+	stream->uid_validity = 0; /* was time(0) */
+
+  if (stream->uid_last < time(0))
+  	stream->uid_last = time (0);  
+  
+    stream->local = fs_get (sizeof (MAILDIRLOCAL));
+  LOCAL->inbox = !strcmp (ucase (strncpy (tmp,stream->mailbox,MAILTMPLEN)),"INBOX") ||
+      !strcmp (stream->mailbox,maildir_file (tmp2,"INBOX"));
+  LOCAL->dir = cpystr (maildir_file (tmp,stream->mailbox)); /* copy dir name */
+                                /* make temporary buffer */
+  LOCAL->buf = (char *) fs_get ((LOCAL->buflen = CHUNKSIZE-1) + 1);
+  LOCAL->scantime = 0;          /* not scanned yet */
+  stream->sequence++;
+  stream->nmsgs = stream->recent = 0;
+
+  maildir_ping_core (stream);
+  maildir_ping (stream);
+/*  if (maildir_ping (stream) && !(stream->nmsgs || stream->silent))
+    printf("Mailbox is empty\n");
+*/
+  return stream;
+
+}
+
+/* Maildir ping mailbox
+ */
+
+long maildir_ping_core (MAILSTREAM *stream)
+{
+  char tmp[MAILTMPLEN];
+  MESSAGECACHE *elt;
+  struct stat sbuf, sbuf2;
+  DIR *dir;
+  struct direct *d;
+  int reloadall = NIL;
+  int uidinvalid = NIL;
+  unsigned long old;
+  long i;
+  long nmsgs = stream->nmsgs;
+  long recent = stream->recent;
+  long nfiles = stream->nmsgs;
+  int silent = stream->silent;
+  char *s, *s2;
+  mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL);
+
+/*  maildir_copynew (LOCAL->dir);
+ */
+  
+  if (stat (LOCAL->dir,&sbuf) < 0) {
+    snprintf (tmp,MAILTMPLEN,"Unable to open maildir: %s",strerror (errno));
+    mm_log (tmp,ERROR);
+    return NIL;
+  }
+
+  /* okay, lets try to figure out the Maildir UID validity. This is done
+     by checking the last modification time of the file .uidvalidity
+     in the rootdir of the Maildir. Any program reordering the files
+     in the directory have to touch this file */
+
+  snprintf(tmp, MAILTMPLEN, "%s/../.uidvalidity", LOCAL->dir);
+  
+  if (stat (tmp,&sbuf2) < 0) {
+	/* no uid validity file found, if uid_validity == 0, we have
+	   to set it to something other than 0, and then create the
+	   .uidvalidity file for future accesses */
+
+	if (stream->uid_validity == 0) {
+		FILE *fl;
+		struct utimbuf tbuf;
+		
+		stream->uid_validity = time(0);
+		tbuf.actime = stream->uid_validity;
+		tbuf.modtime = stream->uid_validity;
+
+		if ((fl = fopen(tmp, "w"))) {
+			fclose(fl);
+			chmod (tmp, S_IRUSR|S_IWUSR);
+			utime(tmp, &tbuf);
+			}
+		}
+		uidinvalid = T; /* UID's are invalid, update them */
+	} else {
+	/* valid file, lets set UID if uid_validity = 0 */
+	if (stream->uid_validity == 0) {
+	stream->uid_validity = sbuf2.st_mtime;
+		}
+	}
+
+  #ifdef NO_UID_VALIDITY
+  uidinvalid = T; /* force the UIDs to be invalid and reset every time,
+  		     useful in an environment without imap servers and
+  		     clients that screw up the UIDs.. i'd leave it to
+  		     OFF until I really need it though... */
+  #endif
+
+  stream->silent = T;  
+  if (sbuf.st_ctime != LOCAL->scantime) {
+    /* update the message list */
+    /* int maildir_namesort(const void *,const void *);
+       int (*mn)(struct direct **, struct direct **) = maildir_namesort; */
+    struct direct **names = NIL;
+    nfiles = scandir (LOCAL->dir,&names,maildir_select,maildir_namesort);
+
+    for (i = 0; i < nfiles; i++) {
+
+	/* check if file has executable bit set */
+	snprintf(tmp, MAILTMPLEN, "%s/%s", LOCAL->dir, names[i]->d_name);
+  	stat (tmp,&sbuf2);
+	if (sbuf2.st_mode & S_IXUSR) {
+		/* executable bit set, modtime is uid */
+		if (sbuf2.st_mtime > stream->uid_last)
+			stream->uid_last = sbuf2.st_mtime+1;
+		}
+	/* this is kept for backwards compatibility */
+        if ((s = strstr (names[i]->d_name,":3,")))
+		s += 3;
+        if (s && (s2 = strstr (s, ",U"))) {
+      		s2 += 2;
+		sscanf(s2, "%d", &old);
+		if (old > stream->uid_last) {
+			stream->uid_last = old+1;
+			}
+		}	
+	
+    }
+
+    mm_critical (stream);	/* go critical */
+    old = stream->uid_last;
+    LOCAL->scantime = sbuf.st_ctime;
+
+				/* check if old files same */
+    for (i = 0; i < stream->nmsgs; i++) {
+
+      if (strcmp ((char *) mail_elt (stream, i + 1)->maildirp,
+		  names[i]->d_name)) {
+	reloadall = T;
+	break;
+      }
+    }
+
+    if (reloadall) { /* files are out of order, rebuild cache */
+
+      i = 1;
+      while (i <= stream->nmsgs)
+				/* clean out cache */
+	if ((elt = (MESSAGECACHE *) (*mc) (stream,i,CH_ELT))) {
+	  fs_give ((void **) &elt->maildirp);
+	  mail_expunged (stream,i);
+	}
+	else
+	  i++;
+      
+      mm_log ("Warning: Mailbox has changed in an unexpected way.  Reloading.",
+	      WARN);
+      stream->nmsgs = 0;
+    }
+    nmsgs = stream->nmsgs;
+    
+    stream->nmsgs = nfiles; /* hm? */    
+
+    for (i = nmsgs; i < nfiles; i++) {
+
+      mail_exists(stream, i+1);
+				/* if newly seen, add to list */
+      (elt = mail_elt (stream, i + 1))->maildirp = (long) cpystr (names[i]->d_name);
+       elt->valid = T;
+
+      /* grab the flags */
+      if ((s = strstr (names[i]->d_name,":3,"))) {
+	s += 3;
+	if (strchr (s,'F'))
+	  elt->flagged = T;
+	if (strchr (s,'R'))
+	  elt->answered = T;
+	if (strchr (s,'S'))
+	  elt->seen = T;
+	if (strchr (s,'T'))
+	  elt->deleted = T;
+      } else if ((s = strstr (names[i]->d_name,":2,"))) {
+	/* this is the :2, id where all files go nowadays */
+	s += 3;
+	if (strchr (s,'F'))
+	  elt->flagged = T;
+	if (strchr (s,'R'))
+	  elt->answered = T;
+	if (strchr (s,'S'))
+	  elt->seen = T;
+	if (strchr (s,'T'))
+	  elt->deleted = T;
+	snprintf(tmp, MAILTMPLEN, "%s/%s", LOCAL->dir, names[i]->d_name);
+  	stat (tmp,&sbuf2);
+	if (sbuf2.st_mode & S_IXUSR) {
+		/* executable bit set, modtime is uid */
+		elt->private.uid = sbuf2.st_mtime;
+		}
+	/* and if we could not retrieve UID from modtime, or if
+	   UIDs are invalid, go here */
+	if (elt->private.uid == 0 || uidinvalid) {
+        	stream->uid_last = (elt = mail_elt (stream,i+1))->private.uid = stream->uid_last+1;
+		maildir_flagmsg(stream, elt);
+		}	
+	s = 0; /* make sure next if statement does not trigger */      
+      	}
+
+      if (s)
+      if ((s2 = strstr (s, ",U"))) {
+      	s2 += 2;
+	sscanf(s2, "%d", &elt->private.uid);
+	if (elt->private.uid == 0 || uidinvalid) {
+        	stream->uid_last = (elt = mail_elt (stream,i+1))->private.uid = stream->uid_last+1;
+		maildir_flagmsg(stream, elt);
+		}	
+	
+      	} else { /* assign new UID */
+        stream->uid_last = (elt = mail_elt (stream,i+1))->private.uid = stream->uid_last+1;
+	elt->recent = T;
+	recent++;
+	maildir_flagmsg(stream, elt); /* store the UID that we assigned to it */
+	}	
+
+
+
+    }
+
+    mm_nocritical (stream);	/* release critical */
+				/* free the names stuff */
+    for (i = 0; i < nfiles; i++)
+      fs_give ((void **) &names[i]);
+    if (names)
+      fs_give ((void **) &names);
+  }
+  stream->silent = silent;
+  mail_exists(stream,nfiles);
+/*  if (!reloadall)  */
+  	mail_recent (stream,recent);
+
+  return T;			/* return that we are alive */
+}
+
+long maildir_ping (MAILSTREAM *stream)
+{
+  maildir_copynew (LOCAL->dir);
+  return maildir_ping_core (stream);
+}
+
+void maildir_copynew (const char *mailbox)
+{
+  char tmp[MAILTMPLEN],file[MAILTMPLEN],newfile[MAILTMPLEN];
+  DIR *dir;
+  struct dirent *d;
+  struct stat sbuf;
+  
+  snprintf (tmp,MAILTMPLEN,"%s/../new",mailbox);
+  if (!(dir = opendir (tmp)))
+    return;
+
+  while (d = readdir (dir)) {
+    if (d->d_name[0] == '.')
+      continue;			/* skip .files */
+
+    snprintf (file,MAILTMPLEN,"%s/%s",tmp,d->d_name);
+				/* make sure this is a normal file */
+    if (stat (file,&sbuf) == 0 && S_ISREG (sbuf.st_mode)) {
+      
+      if (strstr (d->d_name,":3,")) /* this message already has flags */
+	snprintf (newfile,MAILTMPLEN,"%s/%s",mailbox,d->d_name);
+      else
+	snprintf (newfile,MAILTMPLEN,"%s/%s:3,",mailbox,d->d_name);
+      
+				/* move the new mail to the cur dir */
+      if (link (file,newfile) == -1)
+	mm_log("Unable to read new mail!",WARN);
+      else
+	unlink (file);	
+    }
+  }
+  closedir (dir);
+}
+
+int maildir_select (struct direct *name)
+{
+  if (name->d_name[0] != '.')
+    return T;
+
+  return NIL;
+}
+
+/* int maildir_namesort (struct direct **d1,struct direct **d2) */
+int maildir_namesort (const void *d1, const void *d2)
+{
+  return strcmp ((*(struct direct **)d1)->d_name,
+                 (*(struct direct **)d2)->d_name);
+}
+
+
+/* Maildir garbage collect stream
+ */
+
+void maildir_gc (MAILSTREAM *stream,long gcflags)
+{
+  unsigned long i;
+  
+  if (gcflags & GC_TEXTS) {	/* garbage collect texts? */
+				/* flush texts from cache */
+/*    if (LOCAL->hdr) fs_give ((void **) &LOCAL->hdr);
+//    if (stream->text) fs_give ((void **) &stream->text);
+//    stream->msgno = 0;		invalidate stream text
+*/
+  }
+}
+
+/* Maildir close
+ */
+
+void maildir_close (MAILSTREAM *stream, long options)
+{
+  MESSAGECACHE *elt;
+  int i;
+  mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL);
+ 
+/*  CL_EXPUNGE OPTION SUPPORT HERE SOMEWHERE! */
+				/* clean out the cached paths */
+  for (i = 1; i <= stream->nmsgs; i++)
+    if ((elt = (MESSAGECACHE *) (*mc) (stream,i,CH_ELT)) && elt->maildirp) {
+      fs_give ((void **) &elt->maildirp);
+      elt->maildirp = 0; /* otherwise pine coredumps */  
+	}  
+  
+  if (LOCAL) {			/* only if a stream is open */
+    if (LOCAL->dir) fs_give ((void **) &LOCAL->dir);
+    maildir_gc (stream,GC_TEXTS); /* free local cache */
+				/* free local scratch buffer */
+    if (LOCAL->buf) fs_give ((void **) &LOCAL->buf);
+				/* nuke the local data */
+    fs_give ((void **) &stream->local);
+    stream->dtb = NIL;		/* log out the DTB */
+  }
+}
+
+void maildir_check (MAILSTREAM *stream)
+{
+  /* Perhaps in the future this will preserve flags */
+  if (maildir_ping (stream)) mm_log ("Check completed",(long) NIL);   
+}
+
+long maildir_fetchtext (MAILSTREAM *stream,unsigned long msgno,STRING *bs, long flags)
+{
+  unsigned long i;
+  MESSAGECACHE *elt;
+                                /* UID call "impossible" */
+  if (flags & FT_UID) return NIL;
+  elt = mail_elt (stream,msgno);/* get elt */
+                                /* snarf message if don't have it yet */
+  if (!elt->private.msg.text.text.data) {
+    maildir_fetchheader (stream,msgno,&i,flags);
+    if (!elt->private.msg.text.text.data) return NIL;
+  }
+  if (!(flags & FT_PEEK)) {     /* mark as seen */
+    mail_elt (stream,msgno)->seen = T;
+    maildir_flagmsg (stream, mail_elt(stream,msgno));
+    mm_flags (stream,msgno);
+  }
+  if (!elt->private.msg.text.text.data) return NIL;
+  INIT (bs,mail_string,elt->private.msg.text.text.data,
+        elt->private.msg.text.text.size);
+  return T;
+}
+
+
+/* Maildir fetch message header
+ */
+
+char *maildir_fetchheader (MAILSTREAM *stream,unsigned long msgno,
+		unsigned long *length, long flags)
+{
+  unsigned long i,hdrsize;
+  int fd;
+  char *t;
+  char tmp[MAILTMPLEN];
+  char *s,*b;
+  struct stat sbuf;
+  struct tm *tm;
+  MESSAGECACHE *elt;
+  *length = 0;                  /* default to empty */
+  if (flags & FT_UID) return "";/* UID call "impossible" */
+  elt = mail_elt (stream,msgno);/* get elt */
+  if (!elt->private.msg.header.text.data) {
+
+/*    maildir_gc (stream,GC_TEXTS);  invalidate current cache */
+				/* build message file name */
+    snprintf (tmp,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
+    if ((fd = open (tmp,O_RDONLY,NIL)) >= 0) {
+      fstat (fd,&sbuf);		/* get size of message */
+				/* make plausible IMAPish date string */
+      tm = gmtime (&sbuf.st_mtime);
+      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;
+				/* slurp message */
+      read (fd,s = (char *) fs_get (sbuf.st_size + 1),sbuf.st_size);
+      s[sbuf.st_size] = '\0';	/* tie off file */
+      close (fd);		/* close file */
+
+      for (i = 0,b = s; *b && !(i && (*b == '\n')); i = (*b++ == '\n'));
+      hdrsize = (*b ? ++b:b)-s;	/* number of header bytes */
+
+      elt->rfc822_size =          /* size of entire message in CRLF form */
+       (elt->private.msg.header.text.size =
+        strcrlfcpy ((char **) &elt->private.msg.header.text.data,&i,s,
+                    hdrsize)) +
+          (elt->private.msg.text.text.size =
+           strcrlfcpy ((char **) &elt->private.msg.text.text.data,&i,b,
+                       sbuf.st_size - hdrsize));
+      fs_give ((void **) &s);
+    } else return "";
+
+  }
+
+  *length = elt->private.msg.header.text.size;
+  return (char *) elt->private.msg.header.text.data;
+}
+
+void maildir_fast (MAILSTREAM *stream,char *sequence,long flags)
+{
+  unsigned long i,j;
+				/* ugly and slow */
+  if (stream && LOCAL && ((flags & FT_UID) ?
+			  mail_uid_sequence (stream,sequence) :
+			  mail_sequence (stream,sequence)))
+    for (i = 1; i <= stream->nmsgs; i++)
+      if (mail_elt (stream,i)->sequence) maildir_fetchheader (stream,i,&j,NIL);
+}
+
+/* Maildir find list of subscribed mailboxes
+ * Accepts: mail stream
+ *	    pattern to search
+ */
+
+void maildir_list (MAILSTREAM *stream,char *ref, char *pat)
+{
+  DIR *dp;
+  struct direct *d;
+  struct stat sbuf;
+  char *s,*s2,*cp,*np,curdir[MAILTMPLEN],name[MAILTMPLEN],subdir[MAILTMPLEN],rname[MAILTMPLEN];
+
+  strncpy(subdir, pat, MAILTMPLEN);
+
+  s = subdir;
+  s2 = 0;
+  while ((s = strstr(s, "/"))) {
+  	s2 = s;
+	s++;
+	}
+
+  if (s2) { /* pointer to last / */
+  	*s2 = '\0'; /* snip off string */
+	s2++;
+	/*syslog(LOG_INFO, "dir: '%s' pat: '%s'", subdir, s2);*/
+  	snprintf(name, MAILTMPLEN, "%s/%s", myhomedir(), subdir);
+	} else {
+	s2 = pat;
+	snprintf(name, MAILTMPLEN, "%s", myhomedir());
+	strcpy(subdir, "");
+	}
+
+ maildir_listwork(name, stream, s2, subdir, 1);
+
+ if (pmatch ("INBOX", pat))
+ 	mm_list (stream,NIL,"INBOX",LATT_NOINFERIORS);
+
+}
+
+void maildir_listwork(char *name1, MAILSTREAM *stream, char *s2, char *subdir, int flag)
+{
+  DIR *dp;
+  struct direct *d;
+  struct stat sbuf;
+  char *s,*cp,*np,curdir[MAILTMPLEN],rname[MAILTMPLEN],name[MAILTMPLEN];
+  char tmpdir[MAILTMPLEN];
+  
+  strncpy(name, name1, MAILTMPLEN);
+  
+  /*syslog(LOG_INFO, "opendir: '%s'", name);
+  //syslog(LOG_INFO, "subdir: '%s'", subdir);
+   */ 
+  if (dp = opendir (name)) {	/* open directory */
+    while (d = readdir (dp))	/* scan directory, ignore all . names */
+      if (d->d_name[0] != '.' &&
+	  strcmp(d->d_name, "Maildir")) {/* build file name */
+	/* we do not want to list Maildir to customers, because
+	   that might give them weird ideas :) */
+
+	if (subdir[0] != '\0' && subdir[0] != '%' && subdir[0] != '*')
+		snprintf(name, MAILTMPLEN, "%s/%s", subdir, d->d_name);
+	else
+		snprintf(name, MAILTMPLEN, "%s", d->d_name);
+	/*syslog(LOG_INFO, "ls: '%s'", name);*/
+
+	/* this matching might not be correctly implemented	*/
+	if (maildir_file(curdir, name) &&
+      		stat (curdir,&sbuf) == 0 && S_ISDIR (sbuf.st_mode)) {
+		/*syslog(LOG_INFO, "here for some stange reason");*/
+		if (pmatch(d->d_name, s2)) {
+			mm_list (stream,'/',name,NIL);
+			/* call function recursive if last char % */
+			/*syslog(LOG_INFO, "s2: '%s'",s2);*/
+			if (s2[strlen(s2)-1] == '%'
+			||  s2[strlen(s2)-1] == '*') {
+				snprintf(rname, MAILTMPLEN, "%s/%s", name1, name);
+				/*syslog(LOG_INFO, "rname: '%s'", rname);*/
+				maildir_listwork(rname, stream, "%", name, 1);
+				}			
+			}
+		} else
+	if (strlen(curdir) > 4 && pmatch(d->d_name, s2)) { 
+  		int fnlen = strlen (curdir);
+  		curdir[fnlen - 4] = '\0';
+  		/*syslog(LOG_INFO, "fname: '%s'", curdir);*/
+	if (stat (curdir,&sbuf) == 0 && S_ISDIR (sbuf.st_mode)) {
+		/* okay, do not list with NoSelect, since Netscape
+		   does not f*cking honor this flag.. stupid netscape */
+		/*mm_list (stream,'/',name,LATT_NOSELECT);*/
+
+			/* call function recursive if last char % */
+			/*syslog(LOG_INFO, "s2: '%s'",s2);*/
+			if (s2[strlen(s2)-1] == '%' 
+			||  s2[strlen(s2)-1] == '*') {
+				snprintf(rname, MAILTMPLEN, "%s/%s", name1, name);
+				/*syslog(LOG_INFO, "rname: '%s'", rname);*/
+				maildir_listwork(rname, stream, "%", name, 1);
+				}			
+
+		}
+	    }
+
+	}
+      closedir (dp);		/* all done, flush directory */
+      }
+
+}
+
+
+
+
+
+void *maildir_parameters (long function,void *value)
+{
+  return NIL;
+}
+
+long maildir_create (MAILSTREAM *stream,char *mailbox)
+{
+  char tmp[MAILTMPLEN];
+  char err[MAILTMPLEN];
+  char *s, *s2;
+  int fnlen, i;
+  char *subdir_names[] = {"/cur","/new","/tmp",NULL};
+
+				/* must not already exist */
+  if (access (maildir_file (tmp,mailbox),F_OK) == 0) {
+    snprintf (err,MAILTMPLEN,"Can't create mailbox %s: mailbox already exists",mailbox);
+    mm_log (err,ERROR);
+    return NIL;
+  }
+  
+  maildir_file (tmp,mailbox);	/* get file name */
+  fnlen = strlen (tmp);
+  /*syslog(LOG_INFO, "fname: '%s'", tmp);*/
+  tmp[fnlen - 4] = '\0';	/* making main directory's name */
+  fnlen -= 4;
+
+  /* okay, try to add support for adding hiearchys of directories, this
+     is done by scanning for /'s.... */
+     
+  /*syslog(LOG_INFO, "tmp '%s'", tmp);*/
+  s = tmp;
+
+  while ((s = strstr(s, "/")) != 0) {
+	/*syslog(LOG_INFO, "Before make: '%s'", s);*/
+  	*s = '\0';
+  	/*syslog(LOG_INFO, "Trying to make: '%s'", tmp);*/
+	if (mkdir (tmp,0700) && *s != '\0') /* trying to make the dir */
+	  if (errno != EEXIST) {
+	    snprintf (err,MAILTMPLEN,"Can't create mailbox %s: %s %s",
+		     mailbox,tmp,strerror (errno));
+    	     mm_log (err,ERROR);
+             return NIL;
+	  }
+  	*s = '/';
+	s++;
+  	} 
+
+  if (mkdir (tmp,0700)) {	/* try to make new dir */
+    snprintf (err,MAILTMPLEN,"Can't create mailbox %s: %s %s",
+	     mailbox,tmp,strerror (errno));
+    mm_log (err,ERROR);
+    return NIL;
+  }
+
+  /*syslog(LOG_INFO, "create maildir");*/
+  for (i = 0; subdir_names[i]; i++) {
+    strncpy (tmp + fnlen,subdir_names[i],MAILTMPLEN);
+
+    if (mkdir (tmp,0700)) {	/* try to make new dir */
+      snprintf (err,MAILTMPLEN,"Can't create mailbox %s: %s %s",
+	       mailbox,tmp,strerror (errno));
+      mm_log (err,ERROR);
+      return NIL;
+    }
+  }
+
+  return T;			/* return success */
+}
+
+void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt)
+{
+  char oldfile[MAILTMPLEN],newfile[MAILTMPLEN],fn[MAILTMPLEN];
+  struct utimbuf tbuf;
+  char *s;
+
+                                /* build the new filename */
+  snprintf (oldfile,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
+  if ((s = strchr ((char *) elt->maildirp,':'))) *s = '\0';
+  snprintf (fn,MAILTMPLEN,"%s:2,%s%s%s%s",(char *) elt->maildirp,elt->flagged ? "F" : "",
+           elt->answered ? "R" : "",elt->seen ? "S" : "",
+           elt->deleted ? "T" : "");
+  snprintf (newfile,MAILTMPLEN,"%s/%s",LOCAL->dir,fn);
+                                /* rename the file with new flags */
+  if (rename (oldfile,newfile) < 0) {
+    snprintf(oldfile,MAILTMPLEN,"Unable to write flags to disk: %s",strerror (errno));
+    mm_log(oldfile,ERROR);
+    return;
+  }
+                                /* update the file name in cache */
+  fs_give ((void **) &elt->maildirp);
+  elt->maildirp = (long) cpystr (fn);
+
+  /* fix the UID on the file */
+  tbuf.actime = elt->private.uid;
+  tbuf.modtime = elt->private.uid;
+  chmod (newfile, S_IRUSR|S_IWUSR|S_IXUSR);
+  utime (newfile, &tbuf);
+
+}
+
+void maildir_expunge (MAILSTREAM *stream)
+{
+  MESSAGECACHE *elt;
+  unsigned long i = 1;
+  unsigned long n = 0;
+  unsigned long recent = stream->recent;
+  
+  maildir_gc (stream,GC_TEXTS);	/* invalidate texts */
+  mm_critical (stream);		/* go critical */
+  while (i <= stream->nmsgs) {	/* for each message */
+				/* if deleted, need to trash it */
+    if ((elt = mail_elt (stream,i))->deleted) {
+      snprintf (LOCAL->buf,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
+      if (unlink (LOCAL->buf)) {/* try to delete the message */
+	snprintf (LOCAL->buf,MAILTMPLEN,"Expunge of message %ld failed, aborted: %s",i,
+		 strerror (errno));
+	mm_log (LOCAL->buf,WARN);
+	break;
+      }
+				/* free the cached filename */
+      if (elt->maildirp) {
+	      fs_give ((void **) &elt->maildirp);
+	      elt->maildirp = 0; /* otherwise pine coredumps */
+		}
+      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++;			/* otherwise try next message */
+  }
+  if (n) {			/* output the news if any expunged */
+    snprintf (LOCAL->buf,MAILTMPLEN,"Expunged %ld messages",n);
+    mm_log (LOCAL->buf,(long) NIL);
+  }
+  else 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);
+}
+
+/* dont forget to process options in here */
+
+/* modified by sakira@sundent.mine.nu (03.01.13) */
+long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
+{
+  STRING st;
+  MESSAGECACHE *elt;
+  struct stat sbuf;
+  int fd;
+  unsigned long i;
+  char flags[MAILTMPLEN], date[MAILTMPLEN];
+
+				/* 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 (LOCAL->buf, "%s/%s", LOCAL->dir, (char *) elt->maildirp);
+      /*      snprintf (LOCAL->buf,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp); */
+      if ((fd = open (LOCAL->buf,O_RDONLY,NIL)) < 0) return NIL;
+      fstat (fd,&sbuf);		/* get size of message */
+
+      if (!elt->day) {
+	struct tm *tm = gmtime (&sbuf.st_mtime);
+	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;
+      }
+
+      if (sbuf.st_size > LOCAL->buflen) {
+	fs_give((void **) &LOCAL->buf);
+	LOCAL->buf = (char *) fs_get ((LOCAL->buflen = sbuf.st_size) + 1);
+      }
+
+				/* slurp message */
+      read(fd, LOCAL->buf, sbuf.st_size);
+      LOCAL->buf[sbuf.st_size] = '\0';
+      close(fd);
+      /* read (fd, s = (char *) fs_get (sbuf.st_size +1),sbuf.st_size); 
+      s[sbuf.st_size] = '\0';
+      close (fd); */
+
+      INIT (&st,mail_string,(void *) LOCAL->buf,sbuf.st_size);
+      flags[0] = flags[1] = '\0';
+      if (elt->seen) strcat(flags, " \\Seen");
+      if (elt->deleted) strcat(flags, " \\Deleted");
+      if (elt->answered) strcat(flags, " \\Answered");
+      if (elt->draft) strcat(flags, " \\Draft");
+      flags[0] = '(';
+      strcat(flags, ")");
+      mail_date(date, elt);
+      /* snprintf (LOCAL->buf,MAILTMPLEN,"%s%s%s%s%s)",
+	       elt->seen ? " \\Seen" : "",
+	       elt->deleted ? " \\Deleted" : "",
+	       elt->flagged ? " \\Flagged" : "",
+	       elt->answered ? " \\Answered" : "",
+	       (elt->seen || elt->deleted || elt->flagged || elt->answered) ?
+	       "" : " ");
+      LOCAL->buf[0] = '(';
+      mail_date (tmp,elt); */
+
+      if (!mail_append_full (NIL, mailbox, flags, date, &st)) return NIL;
+      if (options & CP_MOVE) elt->deleted = T;
+
+      /* if (!maildir_append (stream,mailbox,LOCAL->buf,tmp,&st)) {
+	fs_give ((void **) &s);	
+	return NIL; 
+	} */
+      /*      fs_give ((void **) &s); */	/* give back temporary space */
+    }
+  return T;			/* return success */
+}
+
+#if 0
+long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
+{
+  STRING st;
+  MESSAGECACHE *elt;
+  struct stat sbuf;
+  int fd;
+  long i;
+  char *s,tmp[MAILTMPLEN];
+				/* 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) {
+      snprintf (LOCAL->buf,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
+      if ((fd = open (LOCAL->buf,O_RDONLY,NIL)) < 0) return NIL;
+      fstat (fd,&sbuf);		/* get size of message */
+				/* slurp message */
+      read (fd,s = (char *) fs_get (sbuf.st_size +1),sbuf.st_size);
+      s[sbuf.st_size] = '\0';	/* tie off file */
+      close (fd);		/* flush message file */
+      INIT (&st,mail_string,(void *) s,sbuf.st_size);
+      snprintf (LOCAL->buf,MAILTMPLEN,"%s%s%s%s%s)",
+	       elt->seen ? " \\Seen" : "",
+	       elt->deleted ? " \\Deleted" : "",
+	       elt->flagged ? " \\Flagged" : "",
+	       elt->answered ? " \\Answered" : "",
+	       (elt->seen || elt->deleted || elt->flagged || elt->answered) ?
+	       "" : " ");
+      LOCAL->buf[0] = '(';	/* open list */
+      mail_date (tmp,elt);	/* generate internal date */
+      if (!maildir_append (stream,mailbox,LOCAL->buf,tmp,&st)) {
+	fs_give ((void **) &s);	/* give back temporary space */
+	return NIL;
+      }
+      fs_give ((void **) &s);	/* give back temporary space */
+    }
+  return T;			/* return success */
+}
+#endif
+
+long maildir_append (MAILSTREAM *stream, char *mailbox, append_t af, void *data)
+{
+  int fd;
+  char c, *s;
+  char *flags, *date;
+  char tmp[MAILTMPLEN],file[MAILTMPLEN],path1[MAILTMPLEN],path2[MAILTMPLEN];
+  MESSAGECACHE elt;
+  STRING *message;
+  long i;
+  long size = 0;
+  long ret = LONGT;
+  short uf = 0;
+  
+  /*  
+     This is intentionaly made static.  Users can ask to save a LOT of messages
+     at once and this program can do that within one second. Dan's assumption
+     that time+pid+hostname always will be unique stops being true in this
+     case. So we will add yet another number to host part of message file's
+     name. Hostname is used only to make filename unique and Dan  explicitly
+     says that "<...>  Other than this [skipping filenames starting at dot] ,
+     readers should not attempt to parse filenames. <...>". Therefore this 
+     addition should be no problem. Am I right, Dan?   --AK
+  */ 
+  
+  static unsigned int transact = 0;
+
+  if (!stream) stream = &maildirproto;
+
+  if (flags) 			/* get flags if given */
+    uf = maildir_getflags (user_flags (&maildirproto),flags);
+
+				/* N.B.: can't use LOCAL->buf for tmp */
+				/* make sure valid mailbox */
+  if (!maildir_isvalid (mailbox, NIL)) {
+    snprintf (tmp,MAILTMPLEN,"Not a valid Maildir mailbox: %s",mailbox);
+    mm_log (tmp,ERROR);
+    return NIL;
+  }
+
+  if (!(*af)(stream, data, &flags, &date, &message)) return NIL;
+
+  mm_critical(stream);	/* go critical */
+  do {
+    if (!SIZE(message)) { /* guard againt zero-length */
+      mm_log("Append of zero-length message", ERROR);
+      ret = NIL;
+      break;
+    }
+
+    /* build file name we will use */
+    snprintf (file,MAILTMPLEN,"%u.%d.%09u.%s:3,%s%s%s%s",
+	      time (0),getpid (),transact++,mylocalhost (),
+	      uf&fFLAGGED ? "F" : "",uf&fANSWERED ? "R" : "",
+	      uf&fSEEN ? "S" : "",uf&fDELETED ? "T" : "");
+				/* build tmp file name */
+    snprintf (path1,MAILTMPLEN,"%s/../tmp/%s",maildir_file (tmp,mailbox),file);
+  
+    if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) {
+      snprintf (tmp,MAILTMPLEN,"Can't open append mailbox: %s",strerror (errno));
+      mm_log (tmp,ERROR);
+      return NIL;
+    }
+
+    i = SIZE (message);		/* get size of message */
+    s = (char *) fs_get (i + 1);	/* get space for the data */
+				/* copy the data w/o CR's */
+    while (i--) if ((c = SNX (message)) != '\015') s[size++] = c;
+				/* write the data */
+    if ((write (fd,s,size) < 0) || fsync (fd)) {
+      unlink (path1);		/* delete message */
+      snprintf (tmp,MAILTMPLEN,"Message append failed: %s",strerror (errno));
+      mm_log (tmp,ERROR);
+      ret = NIL;
+    }
+				/* build final filename to use */
+    snprintf (path2,MAILTMPLEN,"%s/../new/%s",maildir_file (tmp,mailbox),file);
+    if (link (path1,path2) < 0) {
+      snprintf (tmp,MAILTMPLEN,"Message append failed: %s",strerror (errno));
+      mm_log (tmp,ERROR);
+      ret = NIL;
+    }
+    unlink (path1);
+    fs_give ((void **) &s);	/* flush the buffer */
+    close (fd);			/* close the file */
+
+    if (ret) {
+      if (!(*af)(stream, data, &flags, &date, &message)) ret = NIL;
+    }
+  } while(ret && message);
+  
+  mm_nocritical (stream);	/* release critical */
+  return ret;
+}
+
+#if 0
+long maildir_append (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
+		   STRING *message)
+{
+  int fd;
+  char c,*s;
+  char tmp[MAILTMPLEN],file[MAILTMPLEN],path1[MAILTMPLEN],path2[MAILTMPLEN];
+  MESSAGECACHE elt;
+  long i;
+  long size = 0;
+  long ret = LONGT;
+  short uf = 0;
+  
+  /*  
+     This is intentionaly made static.  Users can ask to save a LOT of messages
+     at once and this program can do that within one second. Dan's assumption
+     that time+pid+hostname always will be unique stops being true in this
+     case. So we will add yet another number to host part of message file's
+     name. Hostname is used only to make filename unique and Dan  explicitly
+     says that "<...>  Other than this [skipping filenames starting at dot] ,
+     readers should not attempt to parse filenames. <...>". Therefore this 
+     addition should be no problem. Am I right, Dan?   --AK
+  */ 
+  
+  static unsigned int transact = 0;
+
+  if (flags) 			/* get flags if given */
+    uf = maildir_getflags (user_flags (&maildirproto),flags);
+
+/*  if (date) {			want to preserve date?
+    //syslog(LOG_INFO, "date: '%s'", date);
+				// yes, parse date into an elt
+    if (!mail_parse_date (&elt,date)) {
+      snprintf (tmp,MAILTMPLEN,"Bad date in append: %s",date);
+      mm_log (tmp,ERROR);
+      return NIL;
+    }
+  } */
+				/* N.B.: can't use LOCAL->buf for tmp */
+				/* make sure valid mailbox */
+  if (!maildir_isvalid (mailbox, NIL)) {
+    snprintf (tmp,MAILTMPLEN,"Not a valid Maildir mailbox: %s",mailbox);
+    mm_log (tmp,ERROR);
+    return NIL;
+  }
+				/* build file name we will use */
+  snprintf (file,MAILTMPLEN,"%u.%d.%09u.%s:3,%s%s%s%s",
+	   time (0),getpid (),transact++,mylocalhost (),
+	   uf&fFLAGGED ? "F" : "",uf&fANSWERED ? "R" : "",
+	   uf&fSEEN ? "S" : "",uf&fDELETED ? "T" : "");
+				/* build tmp file name */
+  snprintf (path1,MAILTMPLEN,"%s/../tmp/%s",maildir_file (tmp,mailbox),file);
+  
+  if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) {
+    snprintf (tmp,MAILTMPLEN,"Can't open append mailbox: %s",strerror (errno));
+    mm_log (tmp,ERROR);
+    return NIL;
+  }
+  i = SIZE (message);		/* get size of message */
+  s = (char *) fs_get (i + 1);	/* get space for the data */
+				/* copy the data w/o CR's */
+  while (i--) if ((c = SNX (message)) != '\015') s[size++] = c;
+  mm_critical (stream);		/* go critical */
+				/* write the data */
+  if ((write (fd,s,size) < 0) || fsync (fd)) {
+    unlink (path1);		/* delete message */
+    snprintf (tmp,MAILTMPLEN,"Message append failed: %s",strerror (errno));
+    mm_log (tmp,ERROR);
+    ret = NIL;
+  }
+				/* build final filename to use */
+  snprintf (path2,MAILTMPLEN,"%s/../new/%s",maildir_file (tmp,mailbox),file);
+  if (link (path1,path2) < 0) {
+    snprintf (tmp,MAILTMPLEN,"Message append failed: %s",strerror (errno));
+    mm_log (tmp,ERROR);
+    ret = NIL;
+  }
+  unlink (path1);
+  
+  close (fd);			/* close the file */
+  mm_nocritical (stream);	/* release critical */
+  fs_give ((void **) &s);	/* flush the buffer */
+  return ret;
+}
+#endif
+
+short bezerk_getflags (MAILSTREAM *stream,char *flag)
+{
+  char *t,tmp[MAILTMPLEN],err[MAILTMPLEN];
+  short f = 0;
+  short i,j;
+  if (flag && *flag) {		/* no-op if no flag string */
+				/* check if a list and make sure valid */
+    if ((i = (*flag == '(')) ^ (flag[strlen (flag)-1] == ')')) {
+      mm_log ("Bad flag list",ERROR);
+      return NIL;
+    }
+				/* copy the flag string w/o list construct */
+    strncpy (tmp,flag+i,(j = strlen (flag) - (2*i)));
+    tmp[j] = '\0';
+    t = ucase (tmp);		/* uppercase only from now on */
+
+    while (t && *t) {		/* parse the flags */
+      if (*t == '\\') {		/* system flag? */
+	switch (*++t) {		/* dispatch based on first character */
+	case 'S':		/* possible \Seen flag */
+	  if (t[1] == 'E' && t[2] == 'E' && t[3] == 'N') i = fSEEN;
+	  t += 4;		/* skip past flag name */
+	  break;
+	case 'D':		/* possible \Deleted flag */
+	  if (t[1] == 'E' && t[2] == 'L' && t[3] == 'E' && t[4] == 'T' &&
+	      t[5] == 'E' && t[6] == 'D') i = fDELETED;
+	  t += 7;		/* skip past flag name */
+	  break;
+	case 'F':		/* possible \Flagged flag */
+	  if (t[1] == 'L' && t[2] == 'A' && t[3] == 'G' && t[4] == 'G' &&
+	      t[5] == 'E' && t[6] == 'D') i = fFLAGGED;
+	  t += 7;		/* skip past flag name */
+	  break;
+	case 'A':		/* possible \Answered flag */
+	  if (t[1] == 'N' && t[2] == 'S' && t[3] == 'W' && t[4] == 'E' &&
+	      t[5] == 'R' && t[6] == 'E' && t[7] == 'D') i = fANSWERED;
+	  t += 8;		/* skip past flag name */
+	  break;
+	default:		/* unknown */
+	  i = 0;
+	  break;
+	}
+				/* add flag to flags list */
+	if (i && ((*t == '\0') || (*t++ == ' '))) f |= i;
+      }
+      else {			/* no user flags yet */
+	return f;
+	t = strtok (t," ");	/* isolate flag name */
+	/*	snprintf (err,MAILTMPLEN,"Unknown flag: %.80s",t); */
+	t = strtok (NIL," ");	/* get next flag */
+	/*	mm_log (err,ERROR); */
+      }
+    }
+  }
+  return f;
+}
+
+short maildir_getflags (MAILSTREAM *stream,char *flag)
+{
+  return bezerk_getflags (stream,flag); /* nothing exciting, reuse old code */
+}
+
+long maildir_delete (MAILSTREAM *stream,char *mailbox)
+{
+  DIR *dirp;
+  struct direct *d;
+  int i,j;
+  char tmp[MAILTMPLEN],err[MAILTMPLEN];
+  char *subdir_names[] = {"cur/","new/","tmp/",NULL};
+
+				/* check if mailbox even exists */
+  if (!maildir_isvalid (mailbox,NIL)) {
+/*    sprintf (tmp,"Can't delete mailbox %s: no such mailbox",mailbox);
+    mm_log (tmp,ERROR);
+    return NIL; */
+    /*syslog(LOG_INFO, "Invalid maildir in delete()"); */
+    return T; /* well.. a stupid hack to get by a problem in netscape ..
+    		it remembers folders locally, and if a folder is deleted on
+    		another machine, you have no way removing it on any other
+    		netscapes... */
+  }
+
+				/* get name of directory */
+  i = strlen (maildir_file (tmp,mailbox)) + 1;
+  for (j = 0; subdir_names[j]; j++) {
+    strncpy (tmp + i - 4,subdir_names[j], MAILTMPLEN);
+    if (dirp = opendir (tmp)) {	/* open directory */
+      while (d = readdir (dirp))	/* empty the directory */
+	if (strcmp (d->d_name,".") && strcmp (d->d_name,"..")) {
+	  strncpy (tmp + i,d->d_name, MAILTMPLEN);
+	  /*syslog(LOG_INFO, "unlink1: '%s'");*/
+	  unlink (tmp);
+	}
+      closedir (dirp);		/* flush directory */
+    }
+				/* remove the subdir */
+    tmp[i + 3] = '\0';
+    /*syslog(LOG_INFO, "tmp: '%s'", tmp);*/
+    if (rmdir (tmp)) {
+    /*  sprintf (err,"Can't delete directory %s: %s",tmp,strerror (errno));
+      mm_log (err,ERROR);*/
+    }
+  }
+
+				/* try to remove the directory */
+  *(tmp + i - 5) = '\0';
+  /*syslog(LOG_INFO, "tmp2: '%s'", tmp);*/
+  if (rmdir (tmp)) {
+/*    sprintf (err,"Can't delete mailbox %s: %s",mailbox,strerror (errno));
+    mm_log (err,ERROR);
+    return NIL; */
+  }
+  return T;			/* return success */
+}
+
+long maildir_rename (MAILSTREAM *stream,char *old,char *new)
+{
+  char tmp[MAILTMPLEN],tmpnew[MAILTMPLEN];
+
+				/* old mailbox name must be valid */
+  if (!maildir_isvalid (old,NIL)) {
+    snprintf (tmp,MAILTMPLEN,"Can't rename mailbox %s: no such mailbox",old);
+    mm_log (tmp,ERROR);
+    return NIL;
+  }
+
+				/* new mailbox name must not exist */
+  if (access (maildir_file (tmp,new),F_OK) == 0) {
+    snprintf (tmp,MAILTMPLEN,"Can't rename to mailbox %s: destination already exists",new);
+    mm_log (tmp,ERROR);
+    return NIL;
+  }
+
+				/* try to rename the directory */
+  if (rename (maildir_file (tmp,old),maildir_file (tmpnew,new))) {
+    snprintf (tmp,MAILTMPLEN,"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)
+{
+  char tmp[MAILTMPLEN];
+  return sm_subscribe (mailbox);
+}
+
+long maildir_unsub (MAILSTREAM *stream,char *mailbox)
+{
+  char tmp[MAILTMPLEN];
+  return sm_unsubscribe (mailbox);
+}
+
+void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat)
+{
+ void *sdb = NIL;
+  char *s;
+                                /* get canonical form of name */
+  if ((s = sm_read (&sdb))) {
+    do if (pmatch_full (s,pat,'/')) mm_lsub (stream,'/',s,NIL);
+    while (s = sm_read (&sdb)); /* until no more subscriptions */
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/osdep/unix/maildir.h	Mon Sep 14 19:23:11 2009 +0900
@@ -0,0 +1,58 @@
+/*
+ * Please read maildir.c for license and information
+ *
+ */
+
+#define MAILDIRPATH "Maildir"
+	
+typedef struct maildir_local {
+  unsigned int inbox : 1;	/* if it is an INBOX or not */
+  unsigned int dirty : 1;	/* diskcopy needs updating */
+  char *dir;			/* mail directory name */
+  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)
+
+/* Function prototypes */
+
+DRIVER *maildir_valid (char *name);
+int maildir_isvalid (char *name,long justname);
+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_fetchtext (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);
+char *maildir_fetchheader (MAILSTREAM *stream,unsigned long msgno,
+		unsigned long *length, long flags);
+void maildir_fast (MAILSTREAM *stream,char *sequence,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);
+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_append (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
+   STRING *message); */
+short maildir_getflags (MAILSTREAM *stream,char *flag);
+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);
+void maildir_copynew (const char *mailbox);
+int maildir_select (struct direct *name);
+/* int maildir_namesort (struct direct **d1,struct direct **d2); */
+int maildir_namesort (const void *, const void *);
+void maildir_listwork(char *name, MAILSTREAM *stream, char *s2, char *subdir, int flag);
--- a/src/osdep/unix/tcp_unix.c	Mon Sep 14 15:17:45 2009 +0900
+++ b/src/osdep/unix/tcp_unix.c	Mon Sep 14 19:23:11 2009 +0900
@@ -818,6 +818,20 @@
   return stream->localhost;	/* return local host name */
 }
 
+/* Get $TCPREMOTEHOST || $TCPREMOTEHOST
+ * If invoked via tcpserver or couriertcpd, consult $TCPREMOTEHOST
+ * or $TCPREMOTEIP
+ */
+char* gettcpremoteip()
+{
+  if (getenv("TCPREMOTEHOST") && strcmp("0", getenv("TCPREMOTEHOST"))) {
+    return getenv("TCPREMOTEHOST");
+  } else if (getenv("TCPREMOTEIP")) {
+    return getenv("TCPREMOTEIP");
+  }
+  return "NON-IPv4";
+}
+
 /* TCP/IP get client host address (server calls only)
  * Returns: client host address
  */
@@ -848,6 +862,15 @@
   if (!myClientHost) {
     size_t sadrlen;
     struct sockaddr *sadr = ip_newsockaddr (&sadrlen);
+#ifdef INET6
+    if (getenv("TCPREMOTEIP")) {
+      myClientHost =
+         cpystr((getenv("TCPREMOTEHOST")
+ 		&& strcasecmp("UNKNOWN", getenv("TCPREMOTEHOST")))
+ 		? getenv("TCPREMOTEHOST")
+ 		: getenv("TCPREMOTEIP"));
+    } else
+#endif
     if (getpeername (0,sadr,(void *) &sadrlen)) {
       char *s,*t,*v,tmp[MAILTMPLEN];
       if ((s = getenv (t = "SSH_CLIENT")) ||
@@ -911,7 +934,8 @@
     size_t sadrlen;
     struct sockaddr *sadr = ip_newsockaddr (&sadrlen);
 				/* get stdin's name */
-    if (getsockname (0,sadr,(void *) &sadrlen))
+    if (getsockname (0,sadr,(void *) &sadrlen) ||
+        (myServerPort = ip_sockaddrtoport (sadr)) < 0)
       myServerHost = cpystr (mylocalhost ());
     else {			/* get stdin's name */
       myServerHost = tcp_name (sadr,NIL);
--- a/src/osdep/unix/unix.c	Mon Sep 14 15:17:45 2009 +0900
+++ b/src/osdep/unix/unix.c	Mon Sep 14 19:23:11 2009 +0900
@@ -202,6 +202,7 @@
 
 				/* driver parameters */
 static long unix_fromwidget = T;
+char *myMailSuffix =NIL;	/* home directory name */
 
 /* UNIX mail validate mailbox
  * Accepts: mailbox name
@@ -2401,6 +2402,15 @@
   }
   f->filepos += size;		/* update file position */
 }
+
+/* Return my mail suffix(of qmail or Postfix)
+ * Returns: my mail address extensional suffix
+ */
+
+char *mymailsuffix ()
+{
+  return myMailSuffix ? myMailSuffix : "";
+}
 
 /* MBOX mail routines */
 

yatex.org