imapext-2007

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 diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/APOPtools/Makefile	Mon Sep 14 19:23:11 2009 +0900
     1.3 @@ -0,0 +1,30 @@
     1.4 +#
     1.5 +# install script
     1.6 +#
     1.7 +PERMSMTPDIR	= /usr/local/etc
     1.8 +DEAPOPDIR	= /usr/local/sbin
     1.9 +BINDIR		= /usr/local/bin
    1.10 +CGIDIR		= /usr/local/apache/cgi-bin
    1.11 +
    1.12 +
    1.13 +all:	apopcall
    1.14 +
    1.15 +LDFLAGS	= -lcrypt
    1.16 +
    1.17 +apopcall:	apopcall.c
    1.18 +
    1.19 +
    1.20 +install:
    1.21 +	-@[ -d ${PERMSMTPDIR} ] || mkdir -p ${PERMSMTPDIR}
    1.22 +	install -c -m 700 pop3-record ${PERMSMTPDIR}
    1.23 +	csh -c 'ln -f ${PERMSMTPDIR}/pop3-{record,age}'
    1.24 +	csh -c 'ln -f ${PERMSMTPDIR}/pop3-{record,update}'
    1.25 +	-@[ -d ${DEAPOPDIR} ] || mkdir -p ${DEAPOPDIR}
    1.26 +	install -c -m 700 deapop ${DEAPOPDIR}
    1.27 +	install -c -m 755 apoppasswd ${BINDIR}
    1.28 +
    1.29 +install-cgi:	apopcall
    1.30 +	install -cs -m 4755 -o 0 apopcall ${CGIDIR}/apopcall.cgi
    1.31 +
    1.32 +clean:
    1.33 +	rm apopcall
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/APOPtools/apopcall.c	Mon Sep 14 19:23:11 2009 +0900
     2.3 @@ -0,0 +1,526 @@
     2.4 +#include <stdio.h>
     2.5 +#include <stdlib.h>
     2.6 +#include <string.h>
     2.7 +#include <unistd.h>
     2.8 +#include <sys/types.h>
     2.9 +#include <sys/wait.h>
    2.10 +#include <sys/stat.h>
    2.11 +#include <pwd.h>
    2.12 +#ifdef SHADOW_PASSWD
    2.13 +#include <shadow.h>
    2.14 +#endif
    2.15 +
    2.16 +#ifndef APOPPASSWD
    2.17 +#define APOPPASSWD "/usr/local/bin/apoppasswd"
    2.18 +#endif
    2.19 +#ifndef APOPFILEBASE
    2.20 +#define APOPFILEBASE ".apop"
    2.21 +#endif
    2.22 +#ifndef XADDR_DELIM
    2.23 +#define XADDR_DELIM ('-')
    2.24 +#endif
    2.25 +
    2.26 +char *myname;
    2.27 +
    2.28 +int ishexa(int c) {
    2.29 +    strchr("0123456789ABCDFabcdef", c) ? 1 : 0;
    2.30 +}
    2.31 +
    2.32 +put_form(email, pass, new, new2, suffix, hidden, auth, force)
    2.33 +     char *email, *pass, *new, *new2, *suffix;
    2.34 +     int hidden, auth, force;
    2.35 +     /* auth = 0: old password
    2.36 +               1: base addresse's mail password
    2.37 +               2: unix password */
    2.38 +{
    2.39 +    char *authtype[] = {"old", "base", "unix"};
    2.40 +    char *var[] = {"email", "pass", "new", "new2", "auth", ""};
    2.41 +    char *val[] = {email, pass, new, new2, authtype[auth]};
    2.42 +    char *prm[] = {"",  /* "ユーザ名", */
    2.43 +                   auth ? 
    2.44 +                   ((auth==1)
    2.45 +                    ? "基本メイルアドレス用パスワード<br>Password for Basic Mail address"
    2.46 +                    : "UNIXログインパスワード<br>UNIX login Password")
    2.47 +                   : "古いメイルパスワード<br>Old Mail Password",
    2.48 +                   "新しいメイルパスワード<br>New Mail Password",
    2.49 +                   "新パスワードをもう一回(確認)<br>New Mail Password Again",
    2.50 +		   ""};
    2.51 +    int h=0, i;
    2.52 +
    2.53 +    printf("<form method=POST action\"./%s\">\n", myname);
    2.54 +    printf(" <table border=1>\n");
    2.55 +    for (i=0; var[i][0]; i++) {
    2.56 +        h = hidden || strstr("email,suffix,auth", var[i]);
    2.57 +	if (prm[i][0]) {
    2.58 +            printf("<tr><td>%s</td><td>", prm[i]);
    2.59 +	} else {
    2.60 +	}
    2.61 +        printf("<input name=%s %svalue=\"%s\" length=40 maxlength=40>\n",
    2.62 +               var[i],
    2.63 +               h ? "type=hidden "
    2.64 +               : (strstr(prm[i], "パスワード") ? "type=password " : "<br>"),
    2.65 +               val[i]);
    2.66 +        if (!strcmp(var[i], "suffix")) {
    2.67 +            /* ここでは suffix を入れさせない方がいいかも */
    2.68 +	    /* 表向きのメイルアドレスを表示しておく */
    2.69 +            printf("%s", email);
    2.70 +            /* if (suffix[0]) {
    2.71 +                printf("-%s", suffix);
    2.72 +            } */
    2.73 +            if (auth)
    2.74 +                printf("<br>(新規作成:New Account)");
    2.75 +        }
    2.76 +	if (prm[i][0])
    2.77 +          printf("</td></tr>");
    2.78 +	printf("\n");
    2.79 +    }
    2.80 +    
    2.81 +    printf("</table>\n");
    2.82 +    if (force)
    2.83 +        printf("<input name=force type=hidden value=ON>\n");
    2.84 +    if (auth) {
    2.85 +        char *a[] = {"basic", "unix"};
    2.86 +        printf("<input type=hidden name=auth value=\"%s\">\n", a[auth-1]);
    2.87 +    }
    2.88 +    printf("<input name=OK value=OK type=submit>\n");
    2.89 +    printf("<input name=RESET value=RESET type=reset>\n");
    2.90 +    printf("</form>\n");
    2.91 +    fflush(stdout);
    2.92 +}
    2.93 +
    2.94 +char *decode(char *code) {
    2.95 +    int l=1+strlen(code);
    2.96 +    int i, c, d;
    2.97 +    char *ret = (char*)malloc(l*sizeof(char));
    2.98 +    char *p = code;
    2.99 +    memset(ret, 0, l);
   2.100 +    for (i=0; i<strlen(code); i++) {
   2.101 +	if (code[i] == '+') code[i] = ' ';
   2.102 +    }
   2.103 +    while (code[0] && (p=strchr(code, '%'))
   2.104 +           && ishexa(*(p+1)) && ishexa(*(p+2))) {
   2.105 +        *(p++) = '\0';
   2.106 +        strncat(ret, code, l);
   2.107 +        c = (islower(*p) ? toupper(*p) : *p) - '0';
   2.108 +        p++;
   2.109 +        d = (islower(*p) ? toupper(*p) : *p) - '0';
   2.110 +        if (c > 9) c -= ('A'-'9'-1);
   2.111 +        if (d > 9) d -= ('A'-'9'-1);
   2.112 +        ret[strlen(ret)] = c*16+d;
   2.113 +        code = p+1;
   2.114 +    }
   2.115 +    if (code[0]) strncat(ret, code, l);
   2.116 +    return ret;
   2.117 +}
   2.118 +
   2.119 +#define BSIZE	8192
   2.120 +char **decode_post() {
   2.121 +    char *buf = (char*)malloc(BSIZE*sizeof(char));
   2.122 +    char **post, *p = buf;
   2.123 +    int n=0, i;
   2.124 +    post = (char**)calloc(1, sizeof(char*));
   2.125 +    *buf = '\0';
   2.126 +    fgets(buf, BSIZE, stdin);
   2.127 +    if (strchr("\n\r", buf[strlen(buf)-1])) /* chop */
   2.128 +        buf[strlen(buf)-1] = '\0';
   2.129 +    while (buf[0] && NULL != (p=strchr(buf, '&'))) {
   2.130 +        *p = '\0';
   2.131 +        post[n] = (char*)malloc((p-buf+1)*sizeof(char));
   2.132 +        strcpy(post[n], buf);
   2.133 +        n++;
   2.134 +        post = (char**)realloc(post, (1+n)*sizeof(char*));
   2.135 +        buf = 1+p;
   2.136 +    }
   2.137 +    if (buf[0]) post[n++] = buf;
   2.138 +    /* decode URL encoded */
   2.139 +    for (i=0; i < n; i++) {
   2.140 +        char *p;
   2.141 +        p=post[i];
   2.142 +        post[i] = decode(p);
   2.143 +    }
   2.144 +    post[i] = "";               /* terminator */
   2.145 +    return post;
   2.146 +}
   2.147 +
   2.148 +void footer() {
   2.149 +    puts("</body>\n</html>");
   2.150 +    fflush(stdout);
   2.151 +}
   2.152 +
   2.153 +void fail() {
   2.154 +    printf("パスワード更新に失敗しました<br>\n");
   2.155 +    printf("<a href=\"./\">やり直し</a><br>\n");
   2.156 +    footer();
   2.157 +    exit(1);
   2.158 +}
   2.159 +void success(char *email) {
   2.160 +    printf("<hr>メイルアカウント %s 用のパスワード更新は完了しました。<br>\n",
   2.161 +           email);
   2.162 +    footer();
   2.163 +    exit(0);
   2.164 +}
   2.165 +
   2.166 +int apopfile_existp(char *home, char *suffix, uid_t uid) {
   2.167 +    struct stat st;
   2.168 +    int s;
   2.169 +    int len = strlen(home) + 1
   2.170 +        + strlen(APOPFILEBASE) + strlen(suffix) + 3;
   2.171 +    char *apopfile = (char*)malloc(len);
   2.172 +    if (suffix[0]) {
   2.173 +        snprintf(apopfile, len, "%s/%s%c%s%c",
   2.174 +                 home, APOPFILEBASE, XADDR_DELIM, suffix, 0);
   2.175 +    } else {
   2.176 +        snprintf(apopfile, len, "%s/%s%c", home, APOPFILEBASE, 0);
   2.177 +    }
   2.178 +    seteuid(uid);
   2.179 +    s = stat(apopfile, &st);
   2.180 +    seteuid(0);
   2.181 +    memset(apopfile, '\0', strlen(apopfile));
   2.182 +    free(apopfile);
   2.183 +    return !s;
   2.184 +}
   2.185 +
   2.186 +#ifndef QMAILCONTROL
   2.187 +# define QMAILCONTROL "/var/qmail/control"
   2.188 +#endif
   2.189 +#ifndef MAILTMPLEN
   2.190 +# define MAILTMPLEN 1024
   2.191 +#endif
   2.192 +
   2.193 +/* Convert virtual domain user
   2.194 + */
   2.195 +char* conv_virtualdomain(char *account) {
   2.196 +  char *dom = strchr(account, '@'), *p;
   2.197 +  char vd[MAILTMPLEN+1], rewrite[MAILTMPLEN+1], previous[MAILTMPLEN+1];
   2.198 +  FILE *vdfd;
   2.199 +  int match=0;
   2.200 +  char buf[MAILTMPLEN+1], *s;
   2.201 +  snprintf(vd, MAILTMPLEN, "%s/%s", QMAILCONTROL, "virtualdomains");
   2.202 +  if (NULL == dom) return account;
   2.203 +  dom++;		/* set position of domain part beginning */
   2.204 +  if (dom && NULL != (vdfd = fopen (vd, "r"))) {
   2.205 +    int l = strlen(dom);
   2.206 +    int L = strlen(account);
   2.207 +    while ((s=fgets(buf, MAILTMPLEN, vdfd))) {
   2.208 +      if (p=strchr(s, '#'))
   2.209 +        *p = '\0';			/* zap comments */
   2.210 +      if (!strchr(buf, ':'))
   2.211 +        continue;
   2.212 +      while (s && (strrchr(s, '\n') || strrchr(s, '\r') || strrchr(s, ' ')))
   2.213 +        s[strlen(s)-1] = '\0';
   2.214 +      if (!strncmp(account, s, L) && s[L] == ':' && s[L+1]) { /* user matches */
   2.215 +	match = 3;
   2.216 +        snprintf(rewrite, MAILTMPLEN, "%s-%s", s+L+1, account);
   2.217 +	break;
   2.218 +      }
   2.219 +      if (!strncmp(dom, s, l) && s[l] == ':' && s[l+1]) { /* domain matches */
   2.220 +        match = 2;
   2.221 +	snprintf(rewrite, MAILTMPLEN, "%s%c%s", s+l+1, XADDR_DELIM, account);
   2.222 +	continue;
   2.223 +      }
   2.224 +      if (match < 2 && s[0] == '.') { /* if domain described in wildcard */
   2.225 +        if (p=strchr(s, ':')) {
   2.226 +	  *p = '\0';
   2.227 +	  if (!strcmp(dom+(strlen(dom)-strlen(s)), s)) {
   2.228 +	    if (match == 0
   2.229 +	        || strlen(previous) < strlen(s)) {
   2.230 +	      match = 1;
   2.231 +	      strncpy(previous, s, MAILTMPLEN);
   2.232 +	      snprintf(rewrite, MAILTMPLEN, "%s%c%s", p+1, XADDR_DELIM, account);
   2.233 +	    }
   2.234 +	  }
   2.235 +	}
   2.236 +      }
   2.237 +    }
   2.238 +    fclose(vdfd);
   2.239 +    if (match) {
   2.240 +      p = strchr(rewrite, '@');
   2.241 +      /* fprintf(stderr, "m=%d, rwr=[%s]\n", match, rewrite); */
   2.242 +      if (p) {
   2.243 +        *p = '\0';
   2.244 +      }
   2.245 +      /* fprintf(stderr, "rwr=[%s]\n", rewrite); */
   2.246 +      s = malloc(strlen(rewrite)+1);
   2.247 +      strncpy(s, rewrite, strlen(rewrite)+1);
   2.248 +      memset(vd, 0, sizeof(vd));
   2.249 +      memset(rewrite, 0, sizeof(rewrite));
   2.250 +      memset(previous, 0, sizeof(previous));
   2.251 +      return s;
   2.252 +    }
   2.253 +  }
   2.254 +  /* Then, compare with locals */
   2.255 +  snprintf(vd, MAILTMPLEN, "%s/%s", QMAILCONTROL, "locals");
   2.256 +  if (NULL != (vdfd=fopen(vd, "r"))) {
   2.257 +    while (s=fgets(buf, MAILTMPLEN, vdfd)) {
   2.258 +      if (p=strchr(s, '#')) *p = '\0'; /* zap after comment mark # */
   2.259 +	while (*s && (strrchr(s, '\r')||strrchr(s, '\n')
   2.260 +			||strrchr(s, ' ')||strrchr(s, '\t'))) {
   2.261 +	  *(s+strlen(s)-1) = '\0';
   2.262 +	}
   2.263 +	while (*s && (*s == '\t' || *s == ' ')) s++;
   2.264 +	if (!strncmp(s, dom, strlen(s))) {	/* matches with local domain */
   2.265 +	  int len = dom-account-1;
   2.266 +	  p = (char*)malloc(len+1);
   2.267 +	  memset(p, '\0', len+1);
   2.268 +	  strncpy(p, account, len);
   2.269 +	  return p;
   2.270 +	}
   2.271 +      }
   2.272 +  }
   2.273 +  return NULL; /* invalid domain */
   2.274 +  /* return account; return itself */
   2.275 +}
   2.276 +
   2.277 +void apopcall(char **args) {
   2.278 +    int i=0, sc=0;
   2.279 +    pid_t pid;
   2.280 +    char *email="", *suffix="", *pass="", *new="", *new2 = "", *home="";
   2.281 +    char buf[BUFSIZ], auth, *user;
   2.282 +    FILE *child, *result;
   2.283 +    while (args[i][0]) {
   2.284 +        /* printf("[%s]<br>\n", args[i]); */
   2.285 +        if (!strncmp("email=", args[i], 6)) {
   2.286 +            email = args[i]+6;
   2.287 +        } else if (!strncmp("suffix=", args[i], 7)) {
   2.288 +            suffix = args[i]+7;
   2.289 +        } else if (!strncmp("pass=", args[i], 5)) {
   2.290 +            pass = args[i]+5;
   2.291 +        } else if (!strncmp("new=", args[i], 4)) {
   2.292 +            new = args[i]+4;
   2.293 +        } else if (!strncmp("new2=", args[i], 5)) {
   2.294 +            new2 = args[i]+5;
   2.295 +        } else if (!strncmp("auth=", args[i], 5)) {
   2.296 +            /* "this" or "base" or "unix" */
   2.297 +            auth = args[i][5];
   2.298 +        }
   2.299 +        i++;
   2.300 +    }
   2.301 +    /* Make a backup of original e-mail address */
   2.302 +    /* user = (char*)malloc(1+strlen(email));
   2.303 +       strcpy(user, email);
   2.304 +     */
   2.305 +    user = conv_virtualdomain(email);
   2.306 +    if (NULL == user) {
   2.307 +      printf("そのようなドメインは無効です(%s)<br>\n", strchr(email, '@'));
   2.308 +      printf("入力したメイルアドレスを確認してやり直してください.<br>\n");
   2.309 +      fail();
   2.310 +    }
   2.311 +    if (strchr(user, XADDR_DELIM)) {
   2.312 +	char *p = malloc(1+strlen(user));
   2.313 +	char *q = NULL;
   2.314 +	struct passwd *pwd;
   2.315 +	    /* printf("user=[%s]<br>\n", user); */
   2.316 +
   2.317 +	memset(p, '\0', 1+strlen(user));
   2.318 +	strcpy(p, user);
   2.319 +	while (!(pwd=getpwnam(p)) && (q=strrchr(p, XADDR_DELIM))) {
   2.320 +	    fflush(stdout);
   2.321 +	    *q = '\0';
   2.322 +	}
   2.323 +	if (pwd && q) {
   2.324 +	    q = user+(q-p)+1;
   2.325 +	    user=p;
   2.326 +	    suffix=q;
   2.327 +	}
   2.328 +    }
   2.329 +    if (user[0] && new[0] && new2[0]) {
   2.330 +        int tochild[2], toparent[2];
   2.331 +        pid_t pid;
   2.332 +        int argc=0;
   2.333 +        char **argv;
   2.334 +        struct passwd *pswd;
   2.335 +	char *pstr;
   2.336 +
   2.337 +        if (!(pswd=getpwnam(user))) {
   2.338 +            printf("Unkown user %s.\n", user);
   2.339 +            fflush(stdout);
   2.340 +            fail();
   2.341 +        }
   2.342 +	pstr = pswd->pw_passwd;
   2.343 +#ifdef SHADOW_PASSWD
   2.344 +	{  struct spwd *ss = getspnam(user);
   2.345 +	   pstr = (char*)ss->sp_pwdp;
   2.346 +	}
   2.347 +#endif
   2.348 +        home=pswd->pw_dir;
   2.349 +        argv = (char**)calloc(4, sizeof(char*));
   2.350 +        argv[argc++] = "apoppasswd";
   2.351 +        argv[argc++] = "-s";
   2.352 +        argv[argc++] = "-c";
   2.353 +        /* if old password does not exist,
   2.354 +           then check UNIX password */
   2.355 +#if 0
   2.356 +        if (apopfile_existp(home, suffix, pswd->pw_uid)) { /* no apop-ext exists */
   2.357 +            /* そのまま */
   2.358 +        } else if (apopfile_existp(home, "", pswd->pw_uid)) {/* check base mail password */
   2.359 +            argv = (char**)realloc(argv, (argc+2)*sizeof(char*));
   2.360 +            argv[argc++] = "-b";
   2.361 +        }
   2.362 +#endif
   2.363 +        switch (auth) {
   2.364 +        case 'b': case 'B':
   2.365 +            if (apopfile_existp(home, "", pswd->pw_uid)) {
   2.366 +                argv = (char**)realloc(argv, (argc+2)*sizeof(char*));
   2.367 +                argv[argc++] = "-b";
   2.368 +            } else {
   2.369 +                printf("基本アドレスのパスワードファイルがありません<br>\n");
   2.370 +                fail();
   2.371 +            }
   2.372 +            break;
   2.373 +        case 'u': case 'U':
   2.374 +            if (strcmp(pstr, (char*)crypt(pass, pstr))) {
   2.375 +                printf("UNIX Password not correct.<br>\n");
   2.376 +                /* printf("[%s]vs.[%s]<br>\n",
   2.377 +                   pswd->pw_passwd, crypt(pass, pswd->pw_passwd)); */
   2.378 +                printf("UNIXパスワードと一致しません.<br>\n");
   2.379 +                fflush(stdout);
   2.380 +                fail();
   2.381 +            }
   2.382 +        }
   2.383 +
   2.384 +        if (strlen(new) < 8 || strlen(new2) < 8) {
   2.385 +            printf("New mail password must be more than 7 characters.<br>\n");
   2.386 +            printf("メイルパスワードは8文字以上にしてください。<br>\n");
   2.387 +            fflush(stdout);
   2.388 +            fail();
   2.389 +        }
   2.390 +        if (suffix[0]) {
   2.391 +            argv = (char**)realloc(argv, (argc+3)*sizeof(char*));
   2.392 +            argv[argc++] = "-e";
   2.393 +            argv[argc++] = suffix;
   2.394 +                
   2.395 +        }
   2.396 +        argv[argc++] = NULL;
   2.397 +        if (setgid(pswd->pw_gid) || 0 != setuid(pswd->pw_uid)) {
   2.398 +            printf("Cannot switch to %s\n", user);
   2.399 +	    printf("uid=%d, gid=%d<br>\n", pswd->pw_gid, pswd->pw_uid);
   2.400 +	    printf("メイルパスワード変更サーバの設定不良の可能性があるので<br>\n");
   2.401 +	    printf("お手数ですがこの画面のコピーを添えてシステム管理者");
   2.402 +	    printf("まで御連絡下さい。<br>\n");
   2.403 +            fflush(stdout);
   2.404 +            fail();
   2.405 +        }
   2.406 +
   2.407 +        /* OK, start apopasswd */
   2.408 +        if (pipe(tochild)+pipe(toparent)) {
   2.409 +            printf("Cannot create pipe\n");
   2.410 +            fail();
   2.411 +        }
   2.412 +        if ((pid=fork()) > 0) {
   2.413 +            FILE *child = fdopen(tochild[1], "w");
   2.414 +            close(tochild[0]);
   2.415 +            close(toparent[1]);
   2.416 +            fprintf(child, "PASS %s\nNEW %s\nNEW2 %s\n",
   2.417 +                    pass, new, new2);
   2.418 +            fflush(child);
   2.419 +            fclose(child);
   2.420 +            
   2.421 +        } else if (pid == -1) {
   2.422 +            printf("Cannot fork\n");
   2.423 +            fail();
   2.424 +        } else {
   2.425 +            char *pe = malloc(6+strlen(pswd->pw_dir));
   2.426 +            close(tochild[1]);
   2.427 +            close(toparent[0]);
   2.428 +            dup2(tochild[0], 0);
   2.429 +            dup2(toparent[1], 1);
   2.430 +
   2.431 +            /* setuid section */
   2.432 +
   2.433 +			strcpy(pe, "HOME=");
   2.434 +			strcat(pe, pswd->pw_dir);
   2.435 +            if (putenv(pe)) {
   2.436 +				puts("ga-n! arichan gakkari<br>");
   2.437 +			}
   2.438 +            execv(APOPPASSWD, argv);
   2.439 +
   2.440 +            /* setuid section ends */
   2.441 +            fprintf(stderr, "Cannot exec %s\n", APOPPASSWD);
   2.442 +            fail();
   2.443 +        }
   2.444 +        result = fdopen(toparent[0], "r");
   2.445 +        while (fgets(buf, BUFSIZ, result)) {
   2.446 +            printf("%s<br>", buf);
   2.447 +            fflush(stdout);
   2.448 +            if (strstr(buf, "Success!")) {
   2.449 +                printf("<br>Mail Password changed successfully!<br>\n");
   2.450 +                sc++;
   2.451 +                break;
   2.452 +            } else if (strstr(buf, "mismatch")) {
   2.453 +                printf("二個入れた新パスワードが一致しません.<br>\n");
   2.454 +                break;
   2.455 +            } else if (strstr(buf, "Illegal")) {
   2.456 +                printf("照合用パスワードが違います.<br>--\n");
   2.457 +                break;
   2.458 +            } else if (strstr(buf, "does not exist")) {
   2.459 +                /* try_overwrite(user, pass, new, new2, suffix); */
   2.460 +                if (suffix[0]) {
   2.461 +                    printf("%s-%s", user, suffix);
   2.462 +                } else {
   2.463 +                    printf("%s", user);
   2.464 +                }
   2.465 +                /* ここは来ないことになった(のはず) */
   2.466 +                printf("というメイルアカウントは未作成です<br>\n");
   2.467 +                printf("新規に作る場合はOKボタンをクリック\n");
   2.468 +                put_form(email, pass, new, new2, suffix, 1, 0, 1);
   2.469 +                fflush(stdout);
   2.470 +            }
   2.471 +        }
   2.472 +        fclose(result);
   2.473 +        while (wait(0) != pid) {sleep(1);fputc('.', stderr);}
   2.474 +        if (sc) success(email); else fail();
   2.475 +    } else if (user[0]) {
   2.476 +        struct passwd *pw = getpwnam(user);
   2.477 +        int auth=0;
   2.478 +        if (!pw) {
   2.479 +            printf("そのようなユーザはいません %s<br>\n", user);
   2.480 +            fail();
   2.481 +        }
   2.482 +	home=pw->pw_dir;
   2.483 +        
   2.484 +	printf("%s というメイルアドレスの<br>\n", email);
   2.485 +        printf("メイル専用パスワードを変更します.<br>\n");
   2.486 +        printf("メイルパスワードとUNIXパスワードの違いに気をつけてください.<br>\n");
   2.487 +        printf("新パスワードは8文字以上にしてください.<br>\n");
   2.488 +        printf("New password must be more than or equal to 8 characters.<br>\n");
   2.489 +        if (apopfile_existp(home, suffix, pw->pw_uid)) {
   2.490 +            auth = 0;           /* this password file */
   2.491 +	    printf("「古いメイルパスワード」には、現在<br>\n");
   2.492 +	    printf("<tt>%s</tt><br>\n", email);
   2.493 +	    printf("を読むために指定しているパスワードを入力します。");
   2.494 +        } else if (apopfile_existp(home, "", pw->pw_uid)) {
   2.495 +            auth = 1;           /* basic mail address password */
   2.496 +	    printf("今回は本人認証として基本メイルアドレスのパスワードを");
   2.497 +	    printf("入力しますが、新しくパスワードを設定するのは<br>\n");
   2.498 +	    printf("<tt>%s</tt><br>\n", email);
   2.499 +	    printf("用のパスワードです。基本メイルアドレスのパスワードは");
   2.500 +	    printf("変わりませんので注意してください。");
   2.501 +        } else {
   2.502 +            auth = 2;           /* UNIX login */
   2.503 +        }
   2.504 +        put_form(email, "", "", "", suffix, 0, auth, 0);
   2.505 +        footer();
   2.506 +        exit(0);
   2.507 +    }
   2.508 +    printf("user=[%s]\n", user);
   2.509 +}
   2.510 +
   2.511 +int main(int argc, char* argv[]) {
   2.512 +    char *method = getenv("REQUEST_METHOD");
   2.513 +    char **args;
   2.514 +    myname = argv[0];
   2.515 +    if (method && strcmp(method, "POST") != 0) {
   2.516 +        printf("This program should be used in method:POST.\n");
   2.517 +        fail();
   2.518 +    }
   2.519 +    printf("Content-type: text/html; charset=EUC-JP\n\n");
   2.520 +    printf("<html>\n<head><title>Change Password</title></head>\n");
   2.521 +    printf("<body style=\"background: #f0ffff;\">\n");
   2.522 +    if (getenv("SSL_CIPHER") && getenv("SSL_PROTOCOL")) {
   2.523 +        args = decode_post();
   2.524 +        apopcall(args);
   2.525 +    } else {
   2.526 +        printf("This program can be used only via SSL connection.<br>\n");
   2.527 +        printf("このユーティリティはSSL接続時のみ有効です.<br>\n");
   2.528 +    }
   2.529 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/APOPtools/apoppasswd	Mon Sep 14 19:23:11 2009 +0900
     3.3 @@ -0,0 +1,210 @@
     3.4 +#!/usr/local/bin/perl
     3.5 +# Customize these variables.
     3.6 +# If you change APOPFILEBASE, change the same variable in apopcall.c too.
     3.7 +# See http://www.gentei.org/~yuuji/software/imapext/
     3.8 +
     3.9 +$HOME=$ENV{"HOME"};
    3.10 +
    3.11 +$DEFAULTMAILDIR = "Maildir";	# Must be same as ../src/osdep/unix/Makefile
    3.12 +
    3.13 +$APOPFILEBASE = ".apop";	# "$HOME/$APOPFILEBASE" is the password file
    3.14 +# $APOPFILEBASE = "$DEFAULTMAILDIR/apop";
    3.15 +# $APOPFILEBASE = "Mail/apop";
    3.16 +
    3.17 +$ENCODER = "cat";
    3.18 +# $ENCODER = "gzip";
    3.19 +# $ENCODER = "uuencode $$|gzip";
    3.20 +
    3.21 +$DECODER = "cat";
    3.22 +# $DECODER = "gzip -dc";
    3.23 +# $DECODER = "gzip -dc | uudecode";
    3.24 +
    3.25 +$DOTQMAIL = ".qmail";		# qmail
    3.26 +# $DOTQMAIL = ".forward";	# Postfix
    3.27 +
    3.28 +$XADDR_DELIM = "-";		# qmail
    3.29 +# $XADDR_DELIM = "+";		# Postfix
    3.30 +
    3.31 +$HERE = ".";			# qmail
    3.32 +# $HERE = "~";			# Postfix
    3.33 +
    3.34 +$EXT = "";
    3.35 +$force = 0;
    3.36 +$base = 0;
    3.37 +
    3.38 +$APOPFILE = "$HOME/$APOPFILEBASE";
    3.39 +
    3.40 +sub handler {
    3.41 +	system "stty echo";
    3.42 +	print STDERR "Abort:\n";
    3.43 +	exit 1;
    3.44 +}
    3.45 +
    3.46 +$SIG{'INT'} = $SIG{'KILL'} = $SIG{'QUIT'} = $SIG{'HUP'} = 'handler';
    3.47 +
    3.48 +while ($_=$ARGV[0], /^-.+/ && shift) {
    3.49 +    if (/^-e/) {
    3.50 +	$APOPFILE .= $XADDR_DELIM . ($EXT=shift);
    3.51 +    } elsif (/^-b/) {
    3.52 +	$base++;
    3.53 +    } elsif (/^-c/) {
    3.54 +	$create++;
    3.55 +    } elsif (/^-s/) {
    3.56 +	$stream++;
    3.57 +	# and exit;
    3.58 +    } elsif (/^-h/) {
    3.59 +	&usage; # and exit
    3.60 +    }
    3.61 +}
    3.62 +
    3.63 +sub checkmaildir {
    3.64 +    local($dotqmail) = ("$HOME/$DOTQMAIL");
    3.65 +    local($maildir) = ($DEFAULTMAILDIR);	  # default
    3.66 +    $dotqmail .= "$XADDR_DELIM$EXT" if $EXT;
    3.67 +    $maildir .= "-$EXT" if $EXT;
    3.68 +    unless (-f "$dotqmail") {
    3.69 +	if ($create) {
    3.70 +	    if (open(DQMAIL, "> $dotqmail")) {
    3.71 +		print DQMAIL "$HERE/$maildir/\n";
    3.72 +		print "File [$dotqmail] created\n";
    3.73 +		close(DQMAIL);
    3.74 +	    }
    3.75 +	} else {
    3.76 +	    print "$dotqmail file does not exist.\n";	# should go to stdout
    3.77 +	    print "Your should create $maildir first!\n";
    3.78 +	    print "(-c option automatically makes it)\n";
    3.79 +	    exit 1;
    3.80 +	}
    3.81 +    }
    3.82 +    if (-s $dotqmail) {
    3.83 +	$maildir='';
    3.84 +	if (open(DQMAIL, "< $dotqmail")) {
    3.85 +	    while (<DQMAIL>) {
    3.86 +		s/[\r\n \t]*$//g;
    3.87 +		next if /#/;
    3.88 +		next unless m,\./.*/,;
    3.89 +		chop;			  # strip trailing "/"
    3.90 +		$maildir = $_;
    3.91 +		last;
    3.92 +	    }
    3.93 +	    close(DQMAIL);
    3.94 +	    $maildir = $DEFAULTMAILDIR if $maildir eq '';
    3.95 +	    unless (-d "$HOME/$maildir"
    3.96 +		    && -d "$HOME/$maildir/new"
    3.97 +		    && -d "$HOME/$maildir/cur"
    3.98 +		    && -d "$HOME/$maildir/tmp") {
    3.99 +		if ($create) {
   3.100 +		    mkdir "$HOME/$maildir", 0700;
   3.101 +		    mkdir "$HOME/$maildir/new", 0700;
   3.102 +		    mkdir "$HOME/$maildir/cur", 0700;
   3.103 +		    mkdir "$HOME/$maildir/tmp", 0700;
   3.104 +		    print "Maildir [$maildir/] created\n";
   3.105 +		} else {
   3.106 +		    print "Maildir($maildir) does not exist\n";
   3.107 +		    print "Your should do maildirmake $maildir first!\n";
   3.108 +		    print "(-c option automatically makes it)\n";
   3.109 +		    exit 1;
   3.110 +		}
   3.111 +	    }
   3.112 +	}
   3.113 +    }
   3.114 +}
   3.115 +
   3.116 +sub usage {
   3.117 +    local($mydir, $myname) = ($0 =~ m,(.*)/(.*),);
   3.118 +    print<<_EOU_;
   3.119 +$myname	Change Mail password for imap-4.7+qmailapop
   3.120 +Usage:	$myname [options]
   3.121 +Options are...
   3.122 +	-e EXT		Set target email address to "user-EXT"
   3.123 +	-c		If no .qmail file and Maildir, create them
   3.124 +
   3.125 +_EOU_
   3.126 +    exit 0;
   3.127 +}
   3.128 +
   3.129 +if ($stream) {
   3.130 +    &stream;
   3.131 +    exit; # not reached
   3.132 +}
   3.133 +$OK=0;
   3.134 +until ($OK) {
   3.135 +    system "stty -echo";
   3.136 +    print STDERR "Enter APOP Password: ";
   3.137 +    $new1 = <>;
   3.138 +    print STDERR "\n";
   3.139 +    if (length($new1) == 1) {
   3.140 +	print STDERR "Canceled\n";
   3.141 +	exit 1;
   3.142 +    } elsif (length($new1) < 9) {
   3.143 +	print STDERR "Password is too short!  Please use more than 8 chars.\n";
   3.144 +	next;
   3.145 +    }
   3.146 +    print STDERR "Again APOP Password: ";
   3.147 +    $new2 = <>;
   3.148 +    if ($new1 eq $new2) {
   3.149 +	$OK=1;
   3.150 +    } else {
   3.151 +	print STDERR "\nPassword mismatch! Try again.\n";
   3.152 +    }
   3.153 +}
   3.154 +#OK
   3.155 +&checkmaildir;
   3.156 +system "stty echo";
   3.157 +open(NP, "| $ENCODER > $APOPFILE") || die "Cannot write on $APOPFILE\n";
   3.158 +print NP "$new1";
   3.159 +close(NP);
   3.160 +chmod 0600, $APOPFILE;
   3.161 +print STDERR "\nUpdated APOP password successfully.\n";
   3.162 +
   3.163 +sub stream {				  # Must match with old password
   3.164 +    local($PASS, $old, $new1, $new2, $master) = (0);
   3.165 +    local($masterfile) = ($APOPFILE);
   3.166 +    $masterfile = "$HOME/$APOPFILEBASE" if $base;
   3.167 +    exit 1 if ($> == 0);
   3.168 +    while (<>) {
   3.169 +	chop;
   3.170 +	if (/^PASS (.*)$/i) {
   3.171 +	    $old = $1;
   3.172 +	} elsif (/^NEW (.*)/i) {
   3.173 +	    $new1 = $1;
   3.174 +	} elsif (/^NEW2 (.*)/i) {
   3.175 +	    $new2 = $1;
   3.176 +	}
   3.177 +	last if ("$new1" ne "" && "$new2" ne "");
   3.178 +    }
   3.179 +    if (-s $APOPFILE || ($base && -f $masterfile)) { # Already exist
   3.180 +	if (open(OLD, "$DECODER $masterfile |")) {
   3.181 +	    ($master = <OLD>) =~ s/[\n\r]$//g;
   3.182 +	    close(OLD);
   3.183 +	} else {
   3.184 +	    print "Old password file corrupted.\n";
   3.185 +	    print "Please ask to administrator.\n";
   3.186 +	    exit 1;
   3.187 +	}
   3.188 +	if ($master ne $old) {
   3.189 +	    print "Illegal password\nBye\n";
   3.190 +	    exit 1;
   3.191 +	}
   3.192 +    } 
   3.193 +    if ($new1 ne $new2) {
   3.194 +	print "Password(new) mismatch\nBye\n";
   3.195 +	exit 1;
   3.196 +    }
   3.197 +    # OK, now begin to create!
   3.198 +    &checkmaildir;
   3.199 +    if (open(P, "| $ENCODER > $APOPFILE")) {
   3.200 +	# open success
   3.201 +	print P "$new1\n";
   3.202 +	close(P);
   3.203 +	chmod 0600, $APOPFILE;
   3.204 +	if (-s $APOPFILE) {
   3.205 +	    print "Success!\n";
   3.206 +	    exit 0;
   3.207 +	}
   3.208 +    } else {
   3.209 +	print "Cannot output to $APOPFILE\nBye\n";
   3.210 +	exit 1;
   3.211 +    }
   3.212 +    exit 0;
   3.213 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/APOPtools/deapop	Mon Sep 14 19:23:11 2009 +0900
     4.3 @@ -0,0 +1,4 @@
     4.4 +#!/bin/sh
     4.5 +# deapop script for plain password file
     4.6 +cat "$@"
     4.7 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/APOPtools/deapop.gzip	Mon Sep 14 19:23:11 2009 +0900
     5.3 @@ -0,0 +1,4 @@
     5.4 +#!/bin/sh
     5.5 +# deapop script for gzipped password file
     5.6 +gzcat "$@"
     5.7 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/APOPtools/index.html	Mon Sep 14 19:23:11 2009 +0900
     6.3 @@ -0,0 +1,65 @@
     6.4 +<html>
     6.5 +<head>
     6.6 +<title>
     6.7 +APOP Password
     6.8 +</title>
     6.9 +<style type="text/css">
    6.10 +<!--
    6.11 +.e {color: red; text-decoretion: underline;}
    6.12 +-->
    6.13 +</style>
    6.14 +</head>
    6.15 +
    6.16 +<body bgcolor="azure">
    6.17 +<p>$B$"$J$?$N%a%$%k%"%I%l%9@lMQ$N%Q%9%o!<%I$r@_Dj$^$?$O99?7$7$^$9!#(B</p>
    6.18 +<form method=POST action="./apopcall.cgi">
    6.19 +<table border="1">
    6.20 +<tr><td>$B%a%$%k%"%I%l%9(B:<br>User Name:</td>
    6.21 + <td><input name="email" size="40" maxlength="40"></td></tr>
    6.22 +</table>
    6.23 +<input name="OK" type="submit" value="OK">
    6.24 +<input name="OK" type="reset" value="Clear">
    6.25 +</form>
    6.26 +<ul>
    6.27 + <li> $B=i$a$FMxMQ$9$k>l9g(B
    6.28 +      <p>$B%Q%9%o!<%I$r@_Dj$7$?$$%a%$%k%"%I%l%9$rF~NO$7$F$/$@$5$$!#(B
    6.29 +      $B%a%$%k@lMQ$N%Q%9%o!<%I$r2a5n$K@_Dj$7$F$$$J$$>l9g$O!"(B
    6.30 +      $B<!$N2hLL$GK\?MG'>Z$H$7$F(BUNIX$B%Q%9%o!<%I(B($B%5!<%P$K(B
    6.31 +      $B%m%0%$%s$9$k$H$-$N$b$N(B)$B$rF~NO$7$F$/$@$5$$!#(B</p>
    6.32 + <li> $B3HD%%a%$%k%"%I%l%9$N;XDj(B
    6.33 +      <p>$B4pK\%a%$%k%"%I%l%9$N%f!<%6L>$N8e$m$K(B<span class="e">-$B3HD%;R(B
    6.34 +      </span> ($B%O%$%U%s(B+$B3HD%;R(B)$B$r2C$($?%"%I%l%9$,3HD%%a%$%k%"%I%l%9$K$J(B
    6.35 +      $B$j$^$9!#(B<br>
    6.36 +      $BNc(B:<br>
    6.37 +      $B4pK\%"%I%l%9(B : user@xxx.hogehoge.ac.jp<br>
    6.38 +      $B3HD%%"%I%l%9(B : user-foo@xxx.hogehoge.ac.jp<br>
    6.39 +      ($B$3$N>l9g$N3HD%;R$O(B foo)
    6.40 +      </p>
    6.41 +      <p>$B3HD%%a%$%k%"%I%l%9$O!"3HD%;RItJ,$rJQ$($k$3$H$G(B
    6.42 +      $B2?8D$G$b:n$k$3$H$,$G$-$^$9!#(B
    6.43 +      $B?75,$K:n@.$7$?$$$H$-$O!"3HD%%a%$%k%"%I%l%9$rF~NO$7$F(BOK$B$r(B
    6.44 +      $B2!$7$F$/$@$5$$!#?7$7$$%a%$%k%\%C%/%9$r<+F0E*$K:n@.(B
    6.45 +      $B$9$k$HF1;~$K?73HD%%a%$%k%"%I%l%9@lMQ$N%Q%9%o!<%I$b9T$J$$$^$9!#(B
    6.46 +      </p>
    6.47 +</ul>
    6.48 +<p>$B!Z(B<a href="qmapmore.html">
    6.49 +$B$3$N%5!<%P$GMxMQ$G$-$k%a%$%k%"%I%l%9$K$D$$$F(B</a>$B![(B</p>
    6.50 +<hr>
    6.51 +<ul>
    6.52 + <li> At your first trial to set mail password
    6.53 +      <p>Push [OK] button with your mail address.  We call your
    6.54 +      mail address <em>YourName</em>@xxx.yyy.jp as `basic email address'.<p>
    6.55 +
    6.56 + <li> To create extensional email address<br>
    6.57 +
    6.58 +      <p>On our system, you can have more than one email addresses.  You
    6.59 +      can create any (mail)account name "YourName-xxx"(where xxx is
    6.60 +      any extensional word you might give) which will be delivered to you.  To
    6.61 +      create an extesional email address and/or change the password for
    6.62 +      it, put the extensional email address in the input window.</p>
    6.63 +</ul>
    6.64 +
    6.65 +<hr>
    6.66 +<!--#include virtual="/~yuuji/signature.html"-->
    6.67 +</body>
    6.68 +</html>
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/APOPtools/pop3-age	Mon Sep 14 19:23:11 2009 +0900
     7.3 @@ -0,0 +1,62 @@
     7.4 +#!/bin/sh -
     7.5 +# A sample "POP before SMTP"-enabler script for tcp_wrappers
     7.6 +# This script should be installed in /usr/local/etc
     7.7 +# If you are thinking of using this script on heavily loaded host,
     7.8 +# you had better to choose tcpserver instead of tcp_wrappers.
     7.9 +# 
    7.10 +ALLOWTMP="/var/log/ATMP"
    7.11 +if [ -f /usr/local/etc/hosts.allow ]; then
    7.12 + ALLOW="/usr/local/etc/hosts.allow"
    7.13 +else
    7.14 + ALLOW=/etc/hosts.allow
    7.15 +fi
    7.16 +ALLOWSRC=${ALLOW}.src
    7.17 +ALLOWNEW=${ALLOW}.new
    7.18 +
    7.19 +# for debug
    7.20 +# (env;echo "1=$1") | Mail -s pop3access yuuji
    7.21 +
    7.22 +case $0 in
    7.23 +  *record)
    7.24 +	echo "tcp-env : $RELAYCLIENT : setenv = RELAYCLIENT" >> $ALLOWTMP.1
    7.25 +	;;
    7.26 +  *age)
    7.27 +	rm -f $ALLOWTMP.2
    7.28 +	[ -f $ALLOWTMP.1 ] && mv -f $ALLOWTMP.1 $ALLOWTMP.2
    7.29 +	;;
    7.30 +  *)
    7.31 +	# else generate master hosts.allow file
    7.32 +	;;
    7.33 +esac
    7.34 +touch $ALLOWTMP.1 $ALLOWTMP.2
    7.35 +echo "#
    7.36 +# DO NOT EDIT THIS FILE!
    7.37 +# This file is generated from $ALLOWSRC file.
    7.38 +# Edit it!
    7.39 +#" > $ALLOWNEW
    7.40 +(cat $ALLOWTMP.[12] | sort -u; cat $ALLOWSRC) >> $ALLOWNEW
    7.41 +/bin/mv -f $ALLOWNEW $ALLOW
    7.42 +
    7.43 +# pop3-{age,update,record} for tcp_wrappers ends here
    7.44 +# The following section is the sample routine for tcpserver(ucsp-tcp)
    7.45 +# If you use tcpserver, replace the above section after "case $0...esac"
    7.46 +# by the following section.
    7.47 +# Sample code was contributed by pirozeau(pirozeau@banana-fish.com).
    7.48 +
    7.49 +#TCPREMOTEIP=${TCPREMOTEIP:-undefined}
    7.50 +#RELAYCLIENT=${RELAYCLIENT:-$TCPREMOTEIP}
    7.51 +#ALLOW=/usr/local/etc/smtprule
    7.52 +#case $0 in
    7.53 +#  *record)
    7.54 +#	echo "$RELAYCLIENT:allow,RELAYCLIENT=\"\"" >> $ALLOWTMP.1
    7.55 +#	;;
    7.56 +#  *age)
    7.57 +#	rm -f $ALLOWTMP.2
    7.58 +#	[ -f $ALLOWTMP.1 ] && mv -f $ALLOWTMP.1 $ALLOWTMP.2
    7.59 +#	;;
    7.60 +#  *)
    7.61 +#	# else generate master tcprule file
    7.62 +#	;;
    7.63 +#esac
    7.64 +#touch $ALLOWTMP.1 $ALLOWTMP.2
    7.65 +#(cat $ALLOWTMP.[12] | sort -u; cat ${ALLOW}) | /usr/local/bin/tcprules ${ALLOW}.cdb ${ALLOW}.tmp
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/APOPtools/pop3-record	Mon Sep 14 19:23:11 2009 +0900
     8.3 @@ -0,0 +1,62 @@
     8.4 +#!/bin/sh -
     8.5 +# A sample "POP before SMTP"-enabler script for tcp_wrappers
     8.6 +# This script should be installed in /usr/local/etc
     8.7 +# If you are thinking of using this script on heavily loaded host,
     8.8 +# you had better to choose tcpserver instead of tcp_wrappers.
     8.9 +# 
    8.10 +ALLOWTMP="/var/log/ATMP"
    8.11 +if [ -f /usr/local/etc/hosts.allow ]; then
    8.12 + ALLOW="/usr/local/etc/hosts.allow"
    8.13 +else
    8.14 + ALLOW=/etc/hosts.allow
    8.15 +fi
    8.16 +ALLOWSRC=${ALLOW}.src
    8.17 +ALLOWNEW=${ALLOW}.new
    8.18 +
    8.19 +# for debug
    8.20 +# (env;echo "1=$1") | Mail -s pop3access yuuji
    8.21 +
    8.22 +case $0 in
    8.23 +  *record)
    8.24 +	echo "tcp-env : $RELAYCLIENT : setenv = RELAYCLIENT" >> $ALLOWTMP.1
    8.25 +	;;
    8.26 +  *age)
    8.27 +	rm -f $ALLOWTMP.2
    8.28 +	[ -f $ALLOWTMP.1 ] && mv -f $ALLOWTMP.1 $ALLOWTMP.2
    8.29 +	;;
    8.30 +  *)
    8.31 +	# else generate master hosts.allow file
    8.32 +	;;
    8.33 +esac
    8.34 +touch $ALLOWTMP.1 $ALLOWTMP.2
    8.35 +echo "#
    8.36 +# DO NOT EDIT THIS FILE!
    8.37 +# This file is generated from $ALLOWSRC file.
    8.38 +# Edit it!
    8.39 +#" > $ALLOWNEW
    8.40 +(cat $ALLOWTMP.[12] | sort -u; cat $ALLOWSRC) >> $ALLOWNEW
    8.41 +/bin/mv -f $ALLOWNEW $ALLOW
    8.42 +
    8.43 +# pop3-{age,update,record} for tcp_wrappers ends here
    8.44 +# The following section is the sample routine for tcpserver(ucsp-tcp)
    8.45 +# If you use tcpserver, replace the above section after "case $0...esac"
    8.46 +# by the following section.
    8.47 +# Sample code was contributed by pirozeau(pirozeau@banana-fish.com).
    8.48 +
    8.49 +#TCPREMOTEIP=${TCPREMOTEIP:-undefined}
    8.50 +#RELAYCLIENT=${RELAYCLIENT:-$TCPREMOTEIP}
    8.51 +#ALLOW=/usr/local/etc/smtprule
    8.52 +#case $0 in
    8.53 +#  *record)
    8.54 +#	echo "$RELAYCLIENT:allow,RELAYCLIENT=\"\"" >> $ALLOWTMP.1
    8.55 +#	;;
    8.56 +#  *age)
    8.57 +#	rm -f $ALLOWTMP.2
    8.58 +#	[ -f $ALLOWTMP.1 ] && mv -f $ALLOWTMP.1 $ALLOWTMP.2
    8.59 +#	;;
    8.60 +#  *)
    8.61 +#	# else generate master tcprule file
    8.62 +#	;;
    8.63 +#esac
    8.64 +#touch $ALLOWTMP.1 $ALLOWTMP.2
    8.65 +#(cat $ALLOWTMP.[12] | sort -u; cat ${ALLOW}) | /usr/local/bin/tcprules ${ALLOW}.cdb ${ALLOW}.tmp
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/APOPtools/pop3-record.postfix	Mon Sep 14 19:23:11 2009 +0900
     9.3 @@ -0,0 +1,29 @@
     9.4 +#!/bin/sh -
     9.5 +# A sample "POP before SMTP"-enabler script for Postfix
     9.6 +# This script should be installed in /usr/local/etc.
     9.7 +# This script assumes 
     9.8 +# 
     9.9 +POSTFIXDIR=/etc/postfix
    9.10 +POSTFIXBIN=/usr/libexec/postfix
    9.11 +PATH=$POSTFIXBIN\:$PATH
    9.12 +OKDIR=/var/log
    9.13 +OKCLIENT=$OKDIR/ATMP
    9.14 +CLIENTACCESS=$POSTFIXDIR/client_access
    9.15 +
    9.16 +case $0 in
    9.17 +  *record)
    9.18 +	echo "$RELAYCLIENT	OK" >> $OKCLIENT.1
    9.19 +	;;
    9.20 +  *age)
    9.21 +	rm -f $OKCLIENT.2
    9.22 +	[ -f $OKCLIENT.1 ] && mv -f $OKCLIENT.1 $OKCLIENT.2
    9.23 +	echo '' > $CLIENTACCESS
    9.24 +	# rm -f $CLIENTACCESS.db
    9.25 +	postmap hash:$CLIENTACCESS
    9.26 +	;;
    9.27 +  *)
    9.28 +	# else generate master client_access.db
    9.29 +	;;
    9.30 +esac
    9.31 +touch $OKCLIENT.1 $OKCLIENT.2
    9.32 +cat $OKCLIENT.1 $OKCLIENT.2 | postmap -r -i hash:$CLIENTACCESS
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/APOPtools/pop3-update	Mon Sep 14 19:23:11 2009 +0900
    10.3 @@ -0,0 +1,62 @@
    10.4 +#!/bin/sh -
    10.5 +# A sample "POP before SMTP"-enabler script for tcp_wrappers
    10.6 +# This script should be installed in /usr/local/etc
    10.7 +# If you are thinking of using this script on heavily loaded host,
    10.8 +# you had better to choose tcpserver instead of tcp_wrappers.
    10.9 +# 
   10.10 +ALLOWTMP="/var/log/ATMP"
   10.11 +if [ -f /usr/local/etc/hosts.allow ]; then
   10.12 + ALLOW="/usr/local/etc/hosts.allow"
   10.13 +else
   10.14 + ALLOW=/etc/hosts.allow
   10.15 +fi
   10.16 +ALLOWSRC=${ALLOW}.src
   10.17 +ALLOWNEW=${ALLOW}.new
   10.18 +
   10.19 +# for debug
   10.20 +# (env;echo "1=$1") | Mail -s pop3access yuuji
   10.21 +
   10.22 +case $0 in
   10.23 +  *record)
   10.24 +	echo "tcp-env : $RELAYCLIENT : setenv = RELAYCLIENT" >> $ALLOWTMP.1
   10.25 +	;;
   10.26 +  *age)
   10.27 +	rm -f $ALLOWTMP.2
   10.28 +	[ -f $ALLOWTMP.1 ] && mv -f $ALLOWTMP.1 $ALLOWTMP.2
   10.29 +	;;
   10.30 +  *)
   10.31 +	# else generate master hosts.allow file
   10.32 +	;;
   10.33 +esac
   10.34 +touch $ALLOWTMP.1 $ALLOWTMP.2
   10.35 +echo "#
   10.36 +# DO NOT EDIT THIS FILE!
   10.37 +# This file is generated from $ALLOWSRC file.
   10.38 +# Edit it!
   10.39 +#" > $ALLOWNEW
   10.40 +(cat $ALLOWTMP.[12] | sort -u; cat $ALLOWSRC) >> $ALLOWNEW
   10.41 +/bin/mv -f $ALLOWNEW $ALLOW
   10.42 +
   10.43 +# pop3-{age,update,record} for tcp_wrappers ends here
   10.44 +# The following section is the sample routine for tcpserver(ucsp-tcp)
   10.45 +# If you use tcpserver, replace the above section after "case $0...esac"
   10.46 +# by the following section.
   10.47 +# Sample code was contributed by pirozeau(pirozeau@banana-fish.com).
   10.48 +
   10.49 +#TCPREMOTEIP=${TCPREMOTEIP:-undefined}
   10.50 +#RELAYCLIENT=${RELAYCLIENT:-$TCPREMOTEIP}
   10.51 +#ALLOW=/usr/local/etc/smtprule
   10.52 +#case $0 in
   10.53 +#  *record)
   10.54 +#	echo "$RELAYCLIENT:allow,RELAYCLIENT=\"\"" >> $ALLOWTMP.1
   10.55 +#	;;
   10.56 +#  *age)
   10.57 +#	rm -f $ALLOWTMP.2
   10.58 +#	[ -f $ALLOWTMP.1 ] && mv -f $ALLOWTMP.1 $ALLOWTMP.2
   10.59 +#	;;
   10.60 +#  *)
   10.61 +#	# else generate master tcprule file
   10.62 +#	;;
   10.63 +#esac
   10.64 +#touch $ALLOWTMP.1 $ALLOWTMP.2
   10.65 +#(cat $ALLOWTMP.[12] | sort -u; cat ${ALLOW}) | /usr/local/bin/tcprules ${ALLOW}.cdb ${ALLOW}.tmp
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/APOPtools/qmapmore.html	Mon Sep 14 19:23:11 2009 +0900
    11.3 @@ -0,0 +1,187 @@
    11.4 +<html>
    11.5 +<head>
    11.6 +<title>
    11.7 +APOP Password
    11.8 +</title>
    11.9 +<style type="text/css">
   11.10 +<!--
   11.11 +h1 {text-align: center; text-decoration: underline;}
   11.12 +h2 {color: navy; background-color: lavender;}
   11.13 +.e {color: red; text-decoretion: underline;}
   11.14 +dt (background-color: yellow;}
   11.15 +-->
   11.16 +</style>
   11.17 +</head>
   11.18 +
   11.19 +<body bgcolor="azure">
   11.20 +<h1>
   11.21 + $BK\%a%$%k%5!<%P$K4X$9$kMxMQ<T>\:Y>pJs(B
   11.22 +</h1>
   11.23 +<p>$BL\<!(B</p>
   11.24 +<ul>
   11.25 + <li> <a href="#extaddress">$BK\%5!<%P$GMxMQ$G$-$k%a%$%k%"%I%l%9(B</a>
   11.26 + <li> <a href="#APOP">$B%a%$%k<u?.;~$N%W%m%H%3%k$K$D$$$F(B</a>
   11.27 + <li> <a href="#forward">$BB>$N%a%$%k%5!<%P$X$NE>Aw(B</a>
   11.28 +</ul>
   11.29 +<hr>
   11.30 +
   11.31 +<h2>
   11.32 + <a name="extaddress">$BK\%5!<%P$GMxMQ$G$-$k%a%$%k%"%I%l%9(B</a>
   11.33 +</h2>
   11.34 +<p>$BK\%5!<%P$G$O%a%$%kG[Aw%7%9%F%`$H$7$F(Bqmail$B$rMxMQ$7$F$$$k$N$G!"(B
   11.35 +$BMxMQ<T$N3'$5$s$O2?8D$G$b%a%$%k%"%I%l%9$r:n$k$3$H$,$G$-$^$9!#(B
   11.36 +$B0J2<$N@bL@$G$O!"8D?M$N%a%$%k%"%I%l%9$N%"%+%&%s%HL>ItJ,$r(B
   11.37 +<var>user</var>$B!"%I%a%$%sL>ItJ,$r(B <var>dokkano.ac.jp</var> $B$H(B
   11.38 +$BI=$9$3$H$K$7$^$9!#$D$^$j!"Nc$G;HMQ$9$k%a%$%k%"%I%l%9$O(B
   11.39 +<var>user@dokkano.ac.jp</var>$B$H$J$j$^$9!#$3$N%"%I%l%9$O8f<+?H$N$b$N$HCV(B
   11.40 +$B$-49$($F@bL@$rFI$_?J$a$F$/$@$5$$!#(B</p>
   11.41 +
   11.42 +<dl>
   11.43 + <dt> $B!Z4pK\%a%$%k%"%I%l%9![(B
   11.44 + <dd> <p><var>user@dokkano.ac.jp</var>$B$r4pK\%a%$%k%"%I%l%9$H8F$S$^$9!#%"(B
   11.45 +      $B%+%&%s%H:n@.$HF1;~$KL5>r7o$GMxMQ$G$-$k%a%$%k%"%I%l%9$G$9!#$3$N%"%I(B
   11.46 +      $B%l%9$KFO$$$?%a%$%k$O%5!<%P>e$N$"$J$?@lMQ$N%a%$%k%\%C%/%9$KC_$($i$l(B
   11.47 +      $B$^$9!#JL$N%"%I%l%9$KE>Aw$9$k$3$H$b2DG=$G$9$,!"J}K!$O8e=R$7$^$9!#(B</p>
   11.48 +
   11.49 + <dt> $B!Z3HD%%a%$%k%"%I%l%9![(B
   11.50 + <dd> <p><var>user<span class="e">-xxx</span>@dokkano.ac.jp</var>$B$H$$$&(B
   11.51 +      $B7A<0$N%"%I%l%9$r3HD%%a%$%k%"%I%l%9$H8F$S$^$9!#$"$J$?$N%"%+%&%s%HL>(B
   11.52 +      $B$G;O$^$j!"$=$ND>8e$K%O%$%U%s(B(<span class="e">-</span>)$B$G6h@Z$C$FG$(B
   11.53 +      $B0U$NJ8;zNs$,Mh$k%a%$%k%"%I%l%9$O!"A4$F$"$J$?08$KG[Aw$5$l$^$9!#(B
   11.54 +      <var>user<span class="e">-xxx</span></var>$B$N(B<var>xxx</var>$B$NItJ,$O(B
   11.55 +      <span class="e">$B3HD%;R(B</span>$B$H8F$S!"$I$s$JC18l$G$b9=$$$^$;$s!#(B
   11.56 +      <var>user-123@dokkano.ac.jp, user-job@dokkano.ac.jp,
   11.57 +      user-meeting@dokkano.ac.jp, ...</var>$B$J$I$J$I!"$I$s$J%a%$%k%"%I%l(B
   11.58 +      $B%9$G$b<+J,MQ$K:n@.$9$k$3$H$,$G$-$^$9!#(B
   11.59 +      </p>
   11.60 +</dl>
   11.61 +
   11.62 +<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
   11.63 +$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
   11.64 +<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
   11.65 +$B$?$$%a%$%k%"%I%l%9$r(B<var>user<span
   11.66 +class="e">-xxx</span>@dokkano.ac.jp</var> $B$N7A<0$GF~NO$7$F@h$K?J$a$P<+F0(B
   11.67 +$BE*$K%a%$%k%\%C%/%9$N:n@.$^$G40N;$7$^$9!#$3$N$H$-!"$"$J$?K\?M$N3NG'$H$7$F(B
   11.68 +$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
   11.69 +$B$@$5$$!#(B</p>
   11.70 +
   11.71 +<h2>
   11.72 + <a name="APOP">$B%a%$%k<u?.;~$N%W%m%H%3%k$K$D$$$F(B</a>
   11.73 +</h2>
   11.74 +<p>$B8=:_9-$/MxMQ$5$l$F$$$k%a%$%k<u?.%W%m%H%3%k$G$"$k(BPOP3$B$O!"(B
   11.75 +$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
   11.76 +$B$^$&$N$G!"4JC1$KK5<u$5$l$k$*$=$l$,$"$j$^$9(B($B8=6b<+F0;YJ'5!$NA0$G0E>ZHV9f(B
   11.77 +$B$r@<$K=P$7$J$,$i2!$7$F$$$k;Q$rA[A|$7$F$/$@$5$$(B)$B!#(B</p>
   11.78 +
   11.79 +<p>$B$=$N$h$&$J4m81@-$r9MN8$7$FK\%5!<%P$G$O0J2<$N@_Dj$r9T$J$C$F$$$^$9!#(B</p>
   11.80 +<ul>
   11.81 + <li> POP3$B$O2f!9$NAH?%Fb%M%C%H%o!<%/$+$i$N$_MxMQ$r5v2D(B<br>
   11.82 +      ($BFbIt%M%C%H%o!<%/$K$OIt30<T$O4JC1$K$OF'$_9~$a$J$$$N$G4vJ,0BA4$G$9(B)
   11.83 + <li> $B$=$l0J30$N>l=j$+$i$N<u?.$G$O(BAPOP$B$N$_$r5v2D(B
   11.84 +</ul>
   11.85 +<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
   11.86 +$BK5<u$5$l$?$H$7$F$b85$N%Q%9%o!<%I$O2rFI$G$-$^$;$s!#(BAPOP$B$rMxMQ$9$k>l9g$O$"(B
   11.87 +$B$i$f$k>l=j$+$i$N%a%$%k$N<u?.$,2DG=$K$J$j$^$9!#0BA4@-$r9M$($k$H!"2>$KFbIt(B
   11.88 +$B$+$i$7$+MxMQ$7$J$$>l9g$G$b(BAPOP$B$rMxMQ$5$l$k$3$H$r6/$/$*4+$a$7$^$9!#(B</p>
   11.89 +
   11.90 +<p>APOP$B$rMxMQ$9$k$?$a$NJ}K!$r@bL@$7$^$9!#$J$*!"0J2<$N%a%$%k%j!<%@$G$O(B
   11.91 +APOP$B$,(B<span class="e">$BMxMQ$G$-$^$;$s(B</span>$B$N$G$4Cm0U$/$@$5$$!#(B</p>
   11.92 +<dl>
   11.93 + <dt> $B!Z(BAPOP$B$K(B<span class="e">$BBP1~$7$F$$$J$$(B</span>$B<g$J%a%$%k%j!<%@![(B
   11.94 + <dd> Microsoft Outlook Express<br>
   11.95 +      Microsoft Outlook<br>
   11.96 +      Netscape Messenger
   11.97 + <dt> $B!Z(BAPOP$B$KBP1~$7$F$$$k<g$J%a%$%k%j!<%@![(B
   11.98 + <dd> <ul>
   11.99 +       <li> Windows$BMQ(B<br>
  11.100 +	    <a href="http://www.almail.com/">AL-Mail</a>
  11.101 +	    ($B%7%'%"%&%'%"(B/$B3X@8!&3X=Q5!4XMxMQ$N$_L5NA(B),<br>
  11.102 +	    <a href="http://www.rimarts.co.jp/becky-j.htm">Becky!</a>
  11.103 +	    ($B%7%'%"%&%'%"(B),<br>
  11.104 +	    <a href="http://denshin8.esprix.net/">$BEE?.H,9f(B</a>
  11.105 +	    ($B%U%j!<%=%U%H%&%'%"(B),<br>
  11.106 +	    <a href="http://www.eudora.ne.jp/">Eudora</a>
  11.107 +	    (3$B<oN`$N%i%$%;%s%97ABV(B)
  11.108 +       <li> UNIX$BMQ(B($B0J2<A4$F%U%j!<%=%U%H(B)<br>
  11.109 +	    <a href="http://www.mew.org/index-j.html">Mew</a>,<br>
  11.110 +	    <a href="http://www.gohome.org/wl/index.ja.html">
  11.111 +	    Wanderlust</a>
  11.112 +      </ul>
  11.113 +</dl>
  11.114 +<p>$B0J2<$K$$$/$D$+$N%a%$%k%j!<%@$N(BAPOP$B@_DjJ}K!$r<($7$^$9!#(B</p>
  11.115 +<dl>
  11.116 + <dt> $B!L(BAL-Mail$B!M(B
  11.117 + <dd> <ol>
  11.118 +       <li> $B@_Dj$7$?$$%"%+%&%s%H$rA*$V(B
  11.119 +       <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
  11.120 +	    $B%K%e!<$N!"!V%"%+%&%s%H!W2hLL$K$F1&2<$N!V9bEY$J@_Dj!W$r%/%j%C(B
  11.121 +	    $B%/(B
  11.122 +       <li> $B!V9bEY$J@_Dj!W%&%#%s%I%&$N:82<!V(BAPOP$B$GG'>Z!W$r%A%'%C%/(B
  11.123 +      </ol>
  11.124 + <dt> $B!L(BBecky!$B!M(B
  11.125 + <dd> <ol>
  11.126 +       <li> $B!V%D!<%k(B(T)$B!W"*!V@_Dj!W$G=P$k%&%#%s%I%&$G(B [$B%"%+%&%s%H(B]
  11.127 +	    $B$rA*Br(B
  11.128 +       <li> [$B%"%+%&%s%H(B]$B@_Dj%&%#%s%I%&$N2<$K$"$k(B [$B$=$NB>(B] $B$r(B
  11.129 +	    $B%/%j%C%/(B
  11.130 +       <li> $B%&%#%s%I%&2<It$N(B [APOP$B$r;H$&(B] $B$r%A%'%C%/(B
  11.131 +      </ol>
  11.132 + <dt> $B!L(BEudora 4$B!M(B
  11.133 + <dd> <ol>
  11.134 +       <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
  11.135 +	    $BB&%&%#%s%I%&$K=P$9(B
  11.136 +       <li> APOP$B@_Dj$7$?$$%"%+%&%s%H$r1&%/%j%C%/$7!VJQ99(B(P)$B!W$rA*$V(B
  11.137 +       <li> $B!V%a!<%k$N<u?.!W%a%K%e!<$rA*Br(B
  11.138 +       <li> $B%&%#%s%I%&$N0lHV2<$N(B [$BG'>ZJ}<0(B] $B$G(BAPOP$B$r%A%'%C%/(B
  11.139 +      </ol>
  11.140 +
  11.141 + <dt> $B!L(BMew$B!M(B
  11.142 + <dd> <p>~/.im/Config $B$N(B Imget.Src $B9T$N@_Dj$r0J2<$N$h$&$KJQ$($^$9!#(B</p>
  11.143 +      <blockquote>
  11.144 +       <p><tt>Imget.Src=pop/<span class="e">APOP</span>:user@$B%5!<%PL>(B</tt></p>
  11.145 +      </blockquote>
  11.146 + <dt> $B!L(BWanderlust$B!M(B
  11.147 + <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>
  11.148 +      <blockquote>
  11.149 +       <p><tt>&amp;user<span class="e">/apop</span>@$B%5!<%PL>(B</tt></p>
  11.150 +      </blockquote>
  11.151 +  <hr>
  11.152 +</dl>
  11.153 +<p>$B0J>e$N$$$:$l$N>l9g$b!"3HD%%a%$%k%"%I%l%9$r<u?.$7$?$$$H$-$O%f!<%6L>$H(B
  11.154 +$B$7$F(B user-xxx $B$N$h$&$J3HD%;RIU$NL>A0$r;XDj$7$^$9!#(B</p>
  11.155 +
  11.156 +<h2>
  11.157 + <a name="forward">$BB>$N%a%$%k%5!<%P$X$NE>Aw(B</a>
  11.158 +</h2>
  11.159 +<p>$BK\%5!<%P$KFO$$$?$"$J$?08$N%a%$%k$r!"JL$N%5!<%P$G4IM}$7$F$$$k%a%$%k%"(B
  11.160 +$B%I%l%9$KE>Aw$9$k>l9g$O!"%[!<%`%G%#%l%/%H%j$K$"$k(B .qmail $B$H$$$&%U%!%$%k$K(B
  11.161 +$BE>Aw@h$r=q$-$^$9!#(B</p>
  11.162 +<ol>
  11.163 + <li> FTP$B%/%i%$%"%s%H%=%U%H$rMxMQ$7$F$3$N%5!<%P$K%m%0%$%s$9$k(B
  11.164 + <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
  11.165 +      $B%$%k$,$"$k$N$G$3$l$r<j85$N(BPC$B$K%3%T!<$9$k(B
  11.166 + <li> $B%a%bD"(B(Notepad.exe)$B$J$IE,Ev$J%F%-%9%H%(%G%#%?$rMxMQ$7$F$3$N%U%!%$(B
  11.167 +      $B%k$rJT=8$70J2<$N$h$&$K=q$-49$($F%;!<%V$9$k(B
  11.168 +      <blockquote>
  11.169 +       <tt>&amp;user2@tensosaki.co.jp</tt>
  11.170 +      </blockquote>
  11.171 +      ($B>e5-$NNc$G$O(B <tt>user2@tensosaki.co.jp</tt> $B$,E>Aw@h%"%I%l%9(B)
  11.172 + <li> FTP$B%/%i%$%"%s%H%=%U%H$G:FEY(B .qmail $B%U%!%$%k$r%5!<%P>e$KE>Aw$9$k(B
  11.173 +</ol>
  11.174 +<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
  11.175 +$B;D$7$?$$>l9g$O(B .qmail $B%U%!%$%k$K85!9$"$C$?(B ./Maildir/ $B$H$$$&9T$r>C$5$:$K(B
  11.176 +$BE>AwMQ$N9T$rDI2C$7$^$9!#(B</p>
  11.177 +<blockquote>
  11.178 +<pre>./Maildir/
  11.179 +&amp;user2@tensosaki.co.jp</pre>
  11.180 +</blockquote>
  11.181 +<h3>
  11.182 + $BCm0U(B!
  11.183 +</h3>
  11.184 +<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
  11.185 +ftp$B@\B3$bFbIt$+$i$NMxMQ$N$_$K@)8B$7$F$$$^$9!#$I$&$7$F$b30It%M%C%H%o!<%/(B
  11.186 +$B$+$i(BFTP$B$rMxMQ$9$kI,MW$,$"$k>l9g$O4IM}<T$^$G$4AjCL$/$@$5$$!#(B</p>
  11.187 +
  11.188 +<hr>
  11.189 +</body>
  11.190 +</html>
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/APOPtools/with-tcpserver/0README	Mon Sep 14 19:23:11 2009 +0900
    12.3 @@ -0,0 +1,13 @@
    12.4 +
    12.5 +This directory contains sample files for maintaining ipop3d via daemontools.
    12.6 +
    12.7 +
    12.8 +# make install
    12.9 +
   12.10 +Installation directory can be changed by setting DESTDIR.
   12.11 +eg.
   12.12 +# make DESTDIR=/other/dir install
   12.13 +
   12.14 +Then, edit copied files and change the logging user-id in log/run.
   12.15 +
   12.16 +# ln -s /var/qmail/ipopd /service
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/APOPtools/with-tcpserver/Makefile	Mon Sep 14 19:23:11 2009 +0900
    13.3 @@ -0,0 +1,18 @@
    13.4 +#
    13.5 +TCPDIR=/usr/local/bin
    13.6 +TR=${TCPDIR}/tcprules
    13.7 +DESTDIR	=	/var/qmail/ipopd
    13.8 +LOGMAIN	=	${DESTDIR}/log/main
    13.9 +LOGUSER	=	nobody
   13.10 +
   13.11 +all: pop.cdb
   13.12 +
   13.13 +install:
   13.14 +	-mkdir -p ${DESTDIR}
   13.15 +	tar cf - Makefile log run | (cd ${DESTDIR}; tar xpf -)
   13.16 +	chmod +x ${DESTDIR}/run ${DESTDIR}/log/run
   13.17 +	mkdir ${LOGMAIN}
   13.18 +	chown ${LOGUSER} ${LOGMAIN}
   13.19 +
   13.20 +pop.cdb:	pop
   13.21 +	cat $> | ${TR} $@ pop.tmp
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/APOPtools/with-tcpserver/log/run	Mon Sep 14 19:23:11 2009 +0900
    14.3 @@ -0,0 +1,5 @@
    14.4 +#!/bin/sh
    14.5 +exec env - \
    14.6 +PATH=/bin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/bin \
    14.7 +setuidgid nobody \
    14.8 +multilog t ./main
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/APOPtools/with-tcpserver/pop	Mon Sep 14 19:23:11 2009 +0900
    15.3 @@ -0,0 +1,3 @@
    15.4 +127.0.0.:allow,INTRANET=""
    15.5 +10.0.0.0-127:allow,INTRANET=""
    15.6 +all:allow
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/APOPtools/with-tcpserver/run	Mon Sep 14 19:23:11 2009 +0900
    16.3 @@ -0,0 +1,5 @@
    16.4 +#!/bin/sh
    16.5 +# ipoper should be located in one of the $PATH elements.
    16.6 +exec env - \
    16.7 +PATH=/bin:/usr/bin:/usr/sbin:/var/qmail/ipopd:/usr/local/bin:/usr/local/etc \
    16.8 +tcpserver -HR -c40 -x/var/qmail/ipopd/pop.cdb 0 pop3 ipop3d 2>&1
    17.1 --- a/Makefile	Mon Sep 14 15:17:45 2009 +0900
    17.2 +++ b/Makefile	Mon Sep 14 19:23:11 2009 +0900
    17.3 @@ -252,7 +252,9 @@
    17.4  #	British.  As of 2005, the Julian calendar and the Gregorian calendar
    17.5  #	diverge by 15 days.
    17.6  
    17.7 -EXTRACFLAGS=
    17.8 +# EXTRACFLAGS=-DQMAIL -DRESTRICT_POP -DXADDR_DELIM="+" -DDOTQMAIL=".forward"
    17.9 +## EXTRACFLAGS=-DQMAIL -DRESTRICT_POP
   17.10 +EXTRACFLAGS=-DQMAIL -DRESTRICT_POP -DINET6
   17.11  
   17.12  
   17.13  # Extra linker flags (additional/alternative libraries, etc.)
   17.14 @@ -728,6 +730,7 @@
   17.15  clean:
   17.16  	@echo Removing old processed sources and binaries...
   17.17  	$(SH) -c '$(RM) an ua OSTYPE SPECIALS c-client mtest imapd ipopd mailutil mlock dmail tmail || true'
   17.18 +	$(SH) -c '$(RM) ip6 || true'
   17.19  	$(CD) tools;$(MAKE) clean
   17.20  
   17.21  
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/README.maildir	Mon Sep 14 19:23:11 2009 +0900
    18.3 @@ -0,0 +1,93 @@
    18.4 +Pine 4.0x Maildir c-client module
    18.5 +---------------------------------
    18.6 +
    18.7 +Written by Mattias Larsson <ml@techno.org> <mta@freeit.com>
    18.8 +
    18.9 +This is the second release of my Maildir driver for Pine 4. It is based
   18.10 +on Eric Greens IMAP2bis Maildir driver.
   18.11 +
   18.12 +PLEASE NOTE that this driver has only been tested in the IMAP4rev1 daemon
   18.13 +before. It was just put into Pine 4.00, and it looks like it works, but it
   18.14 +has not been extensively tested. It has been running for 8 months in
   18.15 +production in our IMAP4 daemon though.
   18.16 +
   18.17 +PLEASE NOTE:
   18.18 +
   18.19 +This driver needs to store the UID's of the message in the file somehow. In
   18.20 +the earlier versions of this driver this was done by adding a new maildir
   18.21 +flag (the ,3 flag), however, this solution was not very good since most
   18.22 +other clients could not handle it. Thus I had to find another solution. In
   18.23 +this driver I use a pretty radical method. Any file in the maildir with the
   18.24 +execute bit set has its UID set in the mtime of the file. So you should not
   18.25 +edit the files in here, or in any otherway update the mtime, because then
   18.26 +the UID gets changed. Most clients should not do this, so I think this
   18.27 +solution is compatible with most other clients (if you find one that isn't,
   18.28 +let me know). If you for some reason have to edit a file in the Maildir,
   18.29 +delete the ".uidvalidity" file in the root of the Maildir (ie, the dir where
   18.30 +you find cur/ new/ and tmp/). Alternatively, edit maildir.c and define the
   18.31 +NO_UID_VALIDITY option, which will cause the Maildir to get set new UID's on
   18.32 +every start up. Note that if you are running IMAP and Netscape as a client,
   18.33 +you can't change the UID's, because Netscape do not support the UID validity
   18.34 +flag in the IMAP protocol. So use this with care. 
   18.35 +
   18.36 +Please edit the maildir.c file in any case. There are 3 options you can
   18.37 +set yourself. The default configuration is not suitable for ISPs. If you are
   18.38 +an ISP, or system with many users, you might want to consider setting some
   18.39 +of the options different.
   18.40 +
   18.41 +Ohh, if there are problems compiling it, let me know, and please let me know
   18.42 +what you did to fix it. This thing was developed on Solaris (using both GCC
   18.43 +and SunCC, should work with both), but I haven't tried it on any other
   18.44 +platform. It is also known to compile cleanly on Linux RH5.1
   18.45 +
   18.46 +CONFIGURATION
   18.47 +-------------
   18.48 +
   18.49 +There are a few configurable options. You find these at the top of the
   18.50 +maildir.c file (and it can be found in imap/src/osdep/unix if I'm not all
   18.51 +mistaken). Right now, two options are configurable. By default it is
   18.52 +configured for ISP use, something that you might want to change if you use
   18.53 +it at home.
   18.54 +
   18.55 +HOW TO USE
   18.56 +----------
   18.57 +
   18.58 +Use it as any other c-client driver. There is some option you want to change
   18.59 +if you want all folders to be created as Maildirs (and I can't remember what
   18.60 +the option is from the top of my head). Read the pine documentation.
   18.61 +
   18.62 +CHANGES
   18.63 +-------
   18.64 +
   18.65 +Rel 4.  Coredump problem fixed. In release 3 I decided to user the sparep
   18.66 +	in the message cache so no patching of mail.h would be necessary,
   18.67 +	however, PINE uses this pointer internally for other things, causing
   18.68 +	coredumps when used with the Rel 3. patch.
   18.69 +
   18.70 +Rel 3.	New way of storing UID's (compatible with ,2 clients).
   18.71 +	Multiple inbox patches applied
   18.72 +
   18.73 +Rel 2.  Pine 4 changes.
   18.74 +
   18.75 +Rel 1.  Imap4rev 1 driver
   18.76 +
   18.77 +FINAL NOTES
   18.78 +-----------
   18.79 +
   18.80 +I'll try to maintain and release new versions as soon as I have time over,
   18.81 +which unfortunately does not happen very often in this business ;)
   18.82 +
   18.83 +You can (might) find newer versions of this driver at:
   18.84 +
   18.85 +http://www.freeit.com/mta/
   18.86 +
   18.87 +
   18.88 +Regards,
   18.89 +Daniel Mattias Larsson
   18.90 +
   18.91 +e-mail: ml@techno.org
   18.92 +ph: +46-707-268785
   18.93 +snail-mail:
   18.94 +Industrivagen 4
   18.95 +SE-194 77 Upplands Vasby
   18.96 +SWEDEN
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/README.qmailapop	Mon Sep 14 19:23:11 2009 +0900
    19.3 @@ -0,0 +1,366 @@
    19.4 +//
    19.5 +// qmail+maildir+apop+virtualdomain+POPbeforeSMTP extensions to uw-imapd
    19.6 +// Japanese Document below
    19.7 +//
    19.8 +
    19.9 +[Comentary]
   19.10 +This patch kit enables uw-imapd to handle;
   19.11 +  * maildir
   19.12 +  * qmail's extended mail addresses of user (~/.qmail-ext)
   19.13 +  * Postfix's extended mail addresses of user (~/.forward+ext)
   19.14 +  * Accesses to extended mail addresses (authenticated with ~/.apop-ext)
   19.15 +  * Virtual domain user switching
   19.16 +
   19.17 +Because this package is produced those who want to avail all features above,
   19.18 +we recommend you to turn on all switches for every extension.
   19.19 +Please let me recommend you not to use plain POP3 with this package.
   19.20 +If you want to cling onto POP3, please use qmail-pop3d which comes with
   19.21 +qmail distribution.
   19.22 +
   19.23 +[Configuration]
   19.24 +You can select these compilation switches.
   19.25 +
   19.26 +  Where:	./Makefile
   19.27 +  Switch:	QMAIL
   19.28 +  What:		Support maildir and user's address extension.
   19.29 +  		This switch is requisite.
   19.30 +  
   19.31 +  Where:	./Makefile
   19.32 +  Switch:	INET6
   19.33 +  What:		Support IPv6 address
   19.34 +  		WORKS fine only via ucspi-tcp+ipv6patch
   19.35 +  		If you are using tcpserver-ipv6, set this.
   19.36 +  
   19.37 +  Where:	./Makefile
   19.38 +  Switch:	POSTFIX
   19.39 +  What:		Defaults user address file to ~/.forward and
   19.40 +		extension delimiter to "+".
   19.41 +		Setting this flag on is equavalent to declare
   19.42 +		-DQMAIL -DDOTQMAIL=".forward" -DXADDR_DELIM="+"
   19.43 +		in ./Makefile.
   19.44 +  
   19.45 +  Where:	./Makefile
   19.46 +  Switch:	RESTRICT_POP
   19.47 +  What:		Restrict POP3 access from unsafe network.  Allow
   19.48 +		normal pop3 access only when environment variable
   19.49 +		INTRANET is set.  This can be controled by tcpd with
   19.50 +		/etc/hosts.allow.
   19.51 +  
   19.52 +  Where:	./src/osdep/unix/Makefile
   19.53 +  Switch:	DEFAULTMAILDIR (quoted string)
   19.54 +  What:		Default users' maildir directory when a user does not
   19.55 +		have ~/.qmail file.
   19.56 +		The default value is null.  If null, the default value in
   19.57 +		osdep/unix/maildir.c("Maildir") will be taken.
   19.58 +  
   19.59 +  Where:	./src/osdep/unix/Makefile
   19.60 +  Switch:	QMAILCONTROL (quoted string)
   19.61 +  What:		Default qmail/control directory.
   19.62 +		The default value is "/var/qmail/control"
   19.63 +  
   19.64 +  Where:	./src/osdep/unix/Makefile
   19.65 +  Switch:	USERAPOPFILE (string)
   19.66 +  What:		User's APOP password file relative to their home dir.
   19.67 +		".apop" is set by default.
   19.68 +  		One of recommended values is "Mail/.apop".
   19.69 +		NOTE THAT USERAPOPFILE should NOT be readable by others.
   19.70 +		Do chmod 600 USERAPOPFILE.
   19.71 +  
   19.72 +  Where:	./src/osdep/unix/Makefile
   19.73 +  Switch:	APOPOPEN (string)
   19.74 +  What:		Command name to decode APOP password from USERAPOPFILE
   19.75 +		"/usr/local/sbin/deapop" is set by default.
   19.76 +  		NOTE THAT you should install deapop command too.
   19.77 +		If you don't want to think about this,
   19.78 +		install the following shell script into /usr/local/sbin/deapop
   19.79 +
   19.80 +		  #!/bin/sh
   19.81 +		  cat "$@"
   19.82 +
   19.83 +  Where:	./src/osdep/unix/Makefile
   19.84 +  Switch:	POPBEFORESMTP
   19.85 +  What:		Turn on `POP before SMTP' feature.
   19.86 +  		The next variable POP3RECORDER takes effect when
   19.87 +		this variable is defined.
   19.88 +
   19.89 +  Where:	./src/osdep/unix/Makefile
   19.90 +  Switch:	POP3RECORDER (string)
   19.91 +  What:		Command name to achieve `POP before SMTP'.
   19.92 +		"/usr/local/etc/pop3-record" is set by default.
   19.93 +  		This recorder program should take one argument of
   19.94 +		fully qualified hostname (or IP address) where the POP
   19.95 +		authentication is passed to.
   19.96 +
   19.97 +[NO WARRANTY]
   19.98 +
   19.99 +	This package  comes from absolutely NO WARRANTY.   The author of
  19.100 +	this package is  not responsible for any result  caused by using
  19.101 +	this software.  The  copyright of the extension part  is held by
  19.102 +	HIROSE, Yuuji [yuuji@gentei.org].
  19.103 +
  19.104 +[COPYING]
  19.105 +
  19.106 +	You can re-distribute this  package without any cost except some
  19.107 +	practical cost(magnetical  media or so).   Although this package
  19.108 +	basically obeys  the license  terms in a  file CPYRIGHT  in this
  19.109 +	directory,  there is  one exception;  when you  modify  the code
  19.110 +	against   the  extensional   part  (over   uw-imapd)   and  that
  19.111 +	modification is a kind of bug-fix, modification should be telled
  19.112 +	to  the  author of  extensional  part  if  you are  thinking  of
  19.113 +	re-distribute your modification  to the public.  This limitation
  19.114 +	is  to aim  to  make this  extensional  package reasonably  safe
  19.115 +	always in any time.  Please feel free to hack and distribute it!
  19.116 +
  19.117 +
  19.118 +-- Japanese document follows...
  19.119 +
  19.120 +【qmail+maildir+APOP用POPサーバ】
  19.121 +
  19.122 +	このimapパッケージは、qmailとIMAPを組み合わせて使うこと *ではな
  19.123 +	く* qmail+maildir+APOPを柔軟に利用しようということを目的として作
  19.124 +	られましたのでIMAPでのテストは十分に行なわれていません。このパッ
  19.125 +	ケージは以下のような方を満足させるでしょう。
  19.126 +
  19.127 +	* qmailを利用している
  19.128 +	* mail spool には安全性の高い Maildir 形式を利用し(させ)ている
  19.129 +	* ~/.qmail-ext ファイルによるqmailの拡張アドレスをよく利用している
  19.130 +	* virtual domain を活用しまくっている
  19.131 +
  19.132 +	上記のようなことができるqmailですが、この機能を使いこなすために
  19.133 +	はUNIXマシンにログインしてローカルファイルを見に行くメイルリーダ
  19.134 +	を使うという方法しかありませんでした。これでは不便なので、上記の
  19.135 +	使い分けを認識するPOPサーバを作ろうということで作成したのがこの
  19.136 +	パッケージです。またPOPのみのサーバ利用が多い昨今、リモートから
  19.137 +	の認証にログインパスワードを使わずにメイル専用パスワードを利用さ
  19.138 +	せる変更も行なっています。これによりPOPもAPOP(POPのパスワード認
  19.139 +	証の暗号化版)も共通のパスワードを利用できるようにしました。また、
  19.140 +	POP の場合は既存ユーザのパスワード管理を考えて、認証時にUNIXパス
  19.141 +	ワードも参照するようにしています。
  19.142 +
  19.143 +	もう一点、POPはパスワードをプレインテキストで流すため、外部ネッ
  19.144 +	トワークからの利用は危険です。そこでPOPの利用を一部のネットワー
  19.145 +	クに限定する機能もつけました(tcp_wrappersやtcpserverが必要)。
  19.146 +
  19.147 +【インストール】
  19.148 +
  19.149 +	デフォルト設定では
  19.150 +
  19.151 +	* POP3は拒否する
  19.152 +	* ユーザのパスワード設定ファイルは ~/.apop
  19.153 +	* ~/.apop のデコードプログラムは /usr/local/sbin/deapop
  19.154 +
  19.155 +	となっています。APOP認証はサーバ側で必ず元のパスワードを知る必要
  19.156 +	があります。これまでのAPOPサーバは全てのユーザ毎に管理者権限でパ
  19.157 +	スワードを設定する必要がありました。一見安全そうですが、じつはユー
  19.158 +	ザがパスワードを変更する頻度を限りなくゼロに近づけているだけです。
  19.159 +	そもそもAPOPはサーバ側で元パスワードを取得する必要があるので必ず
  19.160 +	復元可能な形で保存されなければなりません。ということはどんなに凝っ
  19.161 +	た方法で保存しても結局は復号できるのですから、複雑な方法で暗号化
  19.162 +	&格納をすることは手間を増やすだけです。いずれにしてもroot権限さ
  19.163 +	えあれば元のパスワードは簡単に読めるわけですから、最初からユーザ
  19.164 +	自身にパスワード管理をさせてしまっても何ら問題は無く、むしろその
  19.165 +	方がパスワードをこまめに変えてくれる可能性が(ちょりっと)上がりま
  19.166 +	す。ただし、誰にでもパスワードが読めては困るので、パスワードファ
  19.167 +	イルを chmod 600 しておかないとメイルの取り込みが出来ないように
  19.168 +	なっています。またどうしても平文でファイルに保存するのだけはいや
  19.169 +	だーという場合のために、APOPパスワードファイルは 
  19.170 +	/usr/local/sbin/deapop というコマンドを経由して読み込むようになっ
  19.171 +	ています。これにデコードする処理を書いておきます。もし、とくにエ
  19.172 +	ンコードしなくてもいいという場合は
  19.173 +
  19.174 +	  #!/bin/sh
  19.175 +	  cat "$@"
  19.176 +
  19.177 +	というシェルスクリプトでも入れておいてください。このパスワードは
  19.178 +	ログインパスワードとは独立しているのでこれで大きな問題は起こらな
  19.179 +	いでしょう(責任は持ちませんが:-)。
  19.180 +
  19.181 +	コンパイル時の変数は上記英文解説の場所を読んでください。
  19.182 +
  19.183 +【ユーザから見た使い方】
  19.184 +
  19.185 +	まず、~/.qmail に正しくmaildirが設定されていることを確認します。
  19.186 +	maildirをまだ作っていない場合は、
  19.187 +	
  19.188 +	% /var/qmail/bin/maildirmake ~/maildir
  19.189 +
  19.190 +	とし、~/.qmail に
  19.191 +
  19.192 +	./maildir/
  19.193 +
  19.194 +	と書きます。またメイル専用パスワードを ~/.apop に記録します。
  19.195 +	これは apoppasswd コマンドで行ないます。
  19.196 +
  19.197 +	% apoppasswd
  19.198 +
  19.199 +	これで完了です。apoppasswdコマンドは APOPtools/apoppasswd にある
  19.200 +	ので管理者がサイトの環境に手直しした上で一般ユーザのPATHの通る場
  19.201 +	所にインストールして使って下さい。
  19.202 +
  19.203 +	さて、拡張アドレスを使いましょう。ログイン名を login とします。
  19.204 +	login-isogi@hogehoge.co.jp のようなアドレスは ~/.qmail-isogi とい
  19.205 +	うファイルで作成できます。login-isogi 用のmaildirを作ります。
  19.206 +
  19.207 +	% /var/qmail/bin/maildirmake ~/isogidir
  19.208 +
  19.209 +	これを ~/.qmail-isogi に登録します。
  19.210 +
  19.211 +	./isogidir/
  19.212 +
  19.213 +	最後に login-isogi 用のパスワードを設定します。
  19.214 +
  19.215 +	% apoppasswd -e isogi -c
  19.216 +	Enter APOP Password:
  19.217 +
  19.218 +	とすると、maildirの作成とパスワードの設定が同時に行えます。
  19.219 +	maildirとパスワードの作成が完了したら、利用してるメイルリーダの
  19.220 +	APOP アカウントの「アカウント名」をlogin-isogi にして接続します。
  19.221 +
  19.222 +【POP before SMTPについて】
  19.223 +
  19.224 +	まず tcp_wrappers を利用している場合について説明します。
  19.225 +	tcpserverを利用する場合も原理は同じなので仕組みだけ理解してくだ
  19.226 +	さい。
  19.227 +
  19.228 +	tcp_wrapperとtcp-envを組み合わせてSMTPサーバを中継用に使うドメイ
  19.229 +	ンを限定して使っていると思います。これの発展形でPOP接続して来た
  19.230 +	ドメインだけにSMTPサーバを使わせる手法のことを "POP before SMTP" 
  19.231 +	と呼びます。このパッケージでも APOP 接続をしたドメインに対して
  19.232 +	SMTPの中継許可を与えることが出来ます。本パッケージの ./APOPtools 
  19.233 +	ディレクトリにある pop3-* を /usr/local/etc にインストールします。
  19.234 +	3つのファイルの実体は同じです。さらに以下の作業をします。
  19.235 +
  19.236 +	* 原本となる /etc/hosts.allow を /etc/hosts.allow.src にコピー
  19.237 +	* crontab で10分毎に /usr/local/etc/pop3-age を起動させる
  19.238 +
  19.239 +	後者は、大抵のOSの場合 root の crontab に
  19.240 +
  19.241 +	     */10  *  *  *  *   root    /usr/local/etc/pop3-age
  19.242 +
  19.243 +	などと書けば設定できます。pop3-* スクリプトは自身の環境に合わせ
  19.244 +	て適宜修正して下さい。この段階で、tcp_wrapper の定義ファイルは 
  19.245 +	/etc/hosts.allow.src が大元で、/etc/hosts.allow はcronによって自
  19.246 +	動生成されるものとなります。hosts.allowをいじっても自動的に上書
  19.247 +	きされてしまうので、設定を変えるときは *必ず hosts.allow.src を
  19.248 +	編集する* ことに注意して下さい。
  19.249 +
  19.250 +	さらにipop3dを起動するときに接続してきたホストが環境変数
  19.251 +	RELAYCLIENT に入るようにしておきます。/etc/inetd.conf でipop3dを
  19.252 +	起動するときに tcp_wrapper 経由となることを確認します。
  19.253 +
  19.254 +	[/etc/inetd.conf]
  19.255 +	  pop3 stream tcp nowait root /usr/libexec/tcpd /usr/libexec/ipop3d
  19.256 +
  19.257 +	1999年頃以降のPC-UNIXではinetdにデフォルトでtcpdが組み込まれてい
  19.258 +	ることが多いので、inetd.confにtcpdははさまなくて良いこともありま
  19.259 +	す。続いて /etc/hosts.allow.src で環境変数の設定が起きるようにし
  19.260 +	ます。
  19.261 +
  19.262 +	[/etc/hosts.allow.src]
  19.263 +		ipop3d : all : setenv RELAYCLIENT %h
  19.264 +
  19.265 +	これで POPサービスを利用しに来たクライアントのアドレスが環境変数
  19.266 +	に入ります。
  19.267 +
  19.268 +	tcpserverの場合は、付属の pop3-record スクリプトの後半に例がある
  19.269 +	のでそれを利用してください。
  19.270 +
  19.271 +	なお、tcp_wrappers 用の pop3-age スクリプトは負荷の高いマシンで
  19.272 +	は hosts.allow ファイルが空になる可能性があります。lockすれば多
  19.273 +	少ましになるでしょうが完ぺきではありません。もし、hosts.allowの
  19.274 +	書き換えに失敗するような負荷の高い環境で使う場合は tcp_wrappers 
  19.275 +	ではなく、tcpserverでのアクセス制御をすることを強く勧めます。こ
  19.276 +	ちらはロックの必要もなく、安全にアクセス制御ファイルの更新ができ
  19.277 +	ます。
  19.278 +
  19.279 +【POPアクセス制御について】
  19.280 +
  19.281 +	POP3とAPOPは同じポートを使うので「外部からはAPOPだけ許す」などの
  19.282 +	制御はルータやtcp_wrappersなどだけではできません。このipop3dでは、
  19.283 +	生のPOP3は環境変数INTRANETが定義されているときだけに利用を制限す
  19.284 +	ることができます。tcp_wrappers の例を示します。
  19.285 +
  19.286 +		ipop3d : localhost .localnet.hoge.jp \
  19.287 +			: setenv INTRANET : setenv RELAYCLIENT %h
  19.288 +		ipop3d : all : setenv RELAYCLIENT %h
  19.289 +
  19.290 +	としておけば、ローカルネットワーク内だけで生POP3を使うことができ
  19.291 +	ます。
  19.292 +
  19.293 +【virtualdomain機能について】
  19.294 +
  19.295 +	qmailでは /var/qmail/control/virtualdomains を使うことで、ユーザ
  19.296 +	が任意のメイルドメインを持つことができます。これを解釈するように
  19.297 +	しました。/var/qmail/control/virtualdomain ファイルで
  19.298 +
  19.299 +		virtual.hoge.co.jp:user1
  19.300 +		dokan.hoge.co.jp:user2-dokan
  19.301 +
  19.302 +	としておくと、XX@virtual.hoge.co.jp は ~user1/.qmail-XX に配送さ
  19.303 +	れ、YY@dokan.hoge.co.jp は ~user2/.qmail-dokan-YY に配送されます。
  19.304 +	それがMaildirスプールを含む場合、本パッケージのIMAP/POPで取り込
  19.305 +	むことができます。デフォルトではこのためのパスワードはそれぞれ
  19.306 +
  19.307 +		~user1/.apop-XX
  19.308 +		~user2/.apop-dokan-YY
  19.309 +
  19.310 +	ファイルに保存しておかなければなりません。
  19.311 +
  19.312 +【Postfixの拡張アドレス対応について】
  19.313 +
  19.314 +	Postfixによる ~/.forward+ext で発生する拡張アドレスは、その配送
  19.315 +	先がMaildirであれば本パッケージでも利用できます。Postfix のデフォ
  19.316 +	ルト設定の
  19.317 +		forward_path = $home/.forward$recipient_delimiter$extension,
  19.318 +			     $home/.forward
  19.319 +		recipient_delimiter = +
  19.320 +
  19.321 +	のまま Postfix を動かしている場合はトップレベルのMakefileの
  19.322 +	EXTRACFLAGS に -DPOSTFIX を追加して下さい(-DQMAILも必要です)。こ
  19.323 +	れにより、拡張アドレスを決めるファイルが ".forward" に、拡張部分
  19.324 +	を区切る文字列が "+" になります。いずれかを変更している場合はた
  19.325 +	とえば、
  19.326 +
  19.327 +		-DDOTQMAIL=".postfix" -DXADDR_DELIM="-"
  19.328 +
  19.329 +	のように変更できます。もし、Postfix の .forward+ext を利用する場
  19.330 +	合は周辺ツールの APOPtools/apoppasswd, APOPtools/apopcall.c の対
  19.331 +	応する変数も変更する必要があることに注意して下さい。また、パスワー
  19.332 +	ドファイルも ~/.apop-ext ではなく~ /.apop+ext となることに注意が
  19.333 +	必要です。これらが面倒な場合は、Postfix の設定の方で .qmail-ext 
  19.334 +	を見るようにしてしまうのも手です。この場合は
  19.335 +
  19.336 +		recipient_delimiter = -
  19.337 +		forward_path = $home/.forward$recipient_delimiter$extension,
  19.338 +				$home/.qmail$recipient_delimiter$extension,
  19.339 +				$home/.forward
  19.340 +
  19.341 +	とすると ~/.qmail-ext も参照するようになり、デフォルト状態の本パッ
  19.342 +	ケージのまま利用することができるでしょう。
  19.343 +
  19.344 +【Postfixの POP before SMTPについて】
  19.345 +
  19.346 +	main.cf で たとえば次のようにします。
  19.347 +
  19.348 +		smtpd_recipient_restrictions = 
  19.349 +			permit_mynetworks
  19.350 +			check_client_access hash:/etc/postfix/client_access
  19.351 +
  19.352 +	ここで /etc/postfix/client_access は POP before SMTP の許可ホス
  19.353 +	トリストを保持するためのファイル名で、既に使われてはいないものに
  19.354 +	します。配布ディレクトリの APOPtools/pop3-record.postfix は
  19.355 +	/etc/postfix/client_access ファイルをリレー許可判定に使うことを
  19.356 +	前提とした Postfix 用のスクリプトです。
  19.357 +
  19.358 +【謝辞】
  19.359 +
  19.360 +	安井卓さん(tach@debian.or.jp)にはsyslog関係のパッチを頂きました。
  19.361 +	ここに感謝の意を表します。
  19.362 +
  19.363 +【免責】
  19.364 +
  19.365 +	IMAPパッケージに本ドキュメントで説明した拡張機能を追加する部分の
  19.366 +	著作権は広瀬雄二[yuuji@gentei.org]が保持します。このプログラムを
  19.367 +	用いて生じた如何なる結果に対しても著作権者は責任を負いません。
  19.368 +
  19.369 +						2009/9/14 yuuji@gentei.org
    20.1 --- a/src/c-client/auth_log.c	Mon Sep 14 15:17:45 2009 +0900
    20.2 +++ b/src/c-client/auth_log.c	Mon Sep 14 19:23:11 2009 +0900
    20.3 @@ -105,6 +105,10 @@
    20.4    char *ret = NIL;
    20.5    char *user,*pass,*authuser;
    20.6    if (user = (*responder) (PWD_USER,sizeof (PWD_USER),NIL)) {
    20.7 +#ifdef QMAIL
    20.8 +    extern char* conv_virtualdomain(char*);
    20.9 +    user = conv_virtualdomain(user);
   20.10 +#endif
   20.11      if (pass = (*responder) (PWD_PWD,sizeof (PWD_PWD),NIL)) {
   20.12  				/* delimit user from possible admin */
   20.13        if (authuser = strchr (user,'*')) *authuser++ = '\0';
    21.1 --- a/src/c-client/auth_md5.c	Mon Sep 14 15:17:45 2009 +0900
    21.2 +++ b/src/c-client/auth_md5.c	Mon Sep 14 19:23:11 2009 +0900
    21.3 @@ -75,9 +75,11 @@
    21.4  
    21.5  long auth_md5_valid (void)
    21.6  {
    21.7 +#ifndef QMAIL			/* qmail extension can always handle MD5 */
    21.8    struct stat sbuf;
    21.9  				/* server forbids MD5 if no MD5 enable file */
   21.10    if (stat (MD5ENABLE,&sbuf)) auth_md5.server = NIL;
   21.11 +#endif
   21.12    return T;			/* MD5 is otherwise valid */
   21.13  }
   21.14  
   21.15 @@ -186,6 +188,7 @@
   21.16  char *auth_md5_pwd (char *user)
   21.17  {
   21.18    struct stat sbuf;
   21.19 +#ifndef QMAIL
   21.20    int fd = open (MD5ENABLE,O_RDONLY,NIL);
   21.21    unsigned char *s,*t,*buf,*lusr,*lret;
   21.22    char *r;
   21.23 @@ -214,6 +217,77 @@
   21.24      fs_give ((void **) &buf);	/* flush the buffer */
   21.25      close (fd);			/* don't need file any longer */
   21.26    }
   21.27 +#else
   21.28 +# ifndef USERAPOPFILE
   21.29 +#  define USERAPOPFILE ".apop" 
   21.30 +# endif
   21.31 +# ifndef XADDR_DELIM
   21.32 +#  ifdef POSTFIX		/* Same if-condition is in maildir.c.. sorry */
   21.33 +#   define XADDR_DELIM "+"
   21.34 +#  else
   21.35 +#   define XADDR_DELIM "-"
   21.36 +#  endif
   21.37 +# endif
   21.38 +  extern char *myMailSuffix;
   21.39 +  char mycrypt[BUFSIZ+1];
   21.40 +  char *ret = NIL, *tmp=NIL;
   21.41 +  FILE *apopfile = NIL;
   21.42 +  struct passwd *pw = getpwnam(user);
   21.43 +  if (!pw) pw = getpwnam(lcase(tmp=cpystr(user)));
   21.44 +  if (!pw && strstr(user, XADDR_DELIM)) { /* Check qmail alias */
   21.45 +    char tmp[BUFSIZ];
   21.46 +    char *s = user;
   21.47 +    memset(tmp, 0, BUFSIZ);
   21.48 +    while (*s && s && !pw) {
   21.49 +      s = strstr(s, XADDR_DELIM);
   21.50 +      if (!s) break;
   21.51 +      strncpy(tmp, user, s-user);
   21.52 +      s++;
   21.53 +      pw = getpwnam(tmp);
   21.54 +    }
   21.55 +    if (pw) {
   21.56 +      myMailSuffix = lcase(cpystr(s-1));
   21.57 +      user[strlen(tmp)] = '\0'; /* zap suffix */
   21.58 +    }
   21.59 +  }
   21.60 +  if (pw) {
   21.61 +    snprintf(mycrypt, BUFSIZ, "%s/%s", pw->pw_dir, USERAPOPFILE);
   21.62 +    if (NIL != myMailSuffix) strcat(mycrypt, myMailSuffix);
   21.63 +    if (stat(mycrypt, &sbuf) < 0) {
   21.64 +      /* printf("Cannot stat [%s]\015\n", mycrypt); */
   21.65 +      return ret;
   21.66 +    }
   21.67 +    if (sbuf.st_mode & ~(S_IFREG | S_IREAD | S_IWRITE)) {
   21.68 +      /* printf("Your apoppassword file is readable by others. Do chmod 600 %s%c\n", mycrypt, 015); */
   21.69 +      return ret;
   21.70 +    }
   21.71 +#ifdef APOPOPEN
   21.72 +    if (stat(APOPOPEN, &sbuf) >= 0) {	/* if APPOPEN exists */
   21.73 +      /* read apop password via APOPOPEN program */
   21.74 +      int bytes = 3+strlen(APOPOPEN)+strlen(mycrypt);
   21.75 +      char *aproc = (char*) fs_get(bytes);
   21.76 +      snprintf(aproc, bytes, "%s %s%c", APOPOPEN, mycrypt, '\0');
   21.77 +      apopfile = popen(aproc, "r");
   21.78 +      memset(aproc, 0, bytes);
   21.79 +      fs_give((void**)&aproc);
   21.80 +    }
   21.81 +#endif /* APOPOPEN */
   21.82 +    if ((NIL!=apopfile) || (apopfile = fopen( mycrypt, "r" ))) {
   21.83 +      fgets(mycrypt, sizeof(mycrypt) - 1, apopfile);
   21.84 +      fclose(apopfile);
   21.85 +      if (mycrypt[0]) {
   21.86 +	char p = strlen(mycrypt);
   21.87 +	while (p > 0 && (mycrypt[p-1] == '\n' || mycrypt[p-1] == '\r')) {
   21.88 +	   mycrypt[--p] = '\0'; /* zap trailing newlines */
   21.89 +	}
   21.90 +      }
   21.91 +    } else {
   21.92 +      return ret;
   21.93 +    }
   21.94 +    ret = cpystr(mycrypt);
   21.95 +    memset(mycrypt, 0, sizeof(mycrypt));
   21.96 +  }
   21.97 +#endif				/* if QMAIL */
   21.98    return ret;			/* return password */
   21.99  }
  21.100  
  21.101 @@ -231,6 +305,9 @@
  21.102    int i,j;
  21.103    char *ret = NIL;
  21.104    char *s,*authuser,tmp[MAILTMPLEN];
  21.105 +#ifdef QMAIL
  21.106 +  char *userback = cpystr(user);
  21.107 +#endif
  21.108    unsigned char digest[MD5DIGLEN];
  21.109    MD5CONTEXT ctx;
  21.110    char *hex = "0123456789abcdef";
  21.111 @@ -260,7 +337,15 @@
  21.112      memset (tmp,0,MAILTMPLEN);	/* erase sensitive information */
  21.113    }
  21.114    if (!ret) sleep (3);		/* slow down possible cracker */
  21.115 +  else {
  21.116 +    extern void permitsmtp();
  21.117 +    /* permitsmtp();*/
  21.118 +  }
  21.119 +#ifdef QMAIL
  21.120 +  return (ret) ? userback : ret;
  21.121 +#else
  21.122    return ret;
  21.123 +#endif
  21.124  }
  21.125  
  21.126  /*
    22.1 --- a/src/c-client/mail.c	Mon Sep 14 15:17:45 2009 +0900
    22.2 +++ b/src/c-client/mail.c	Mon Sep 14 19:23:11 2009 +0900
    22.3 @@ -6081,6 +6081,9 @@
    22.4      if (auth->server && !compare_cstring (auth->name,mechanism))
    22.5        return (!(auth->flags & AU_DISABLE) &&
    22.6  	      ((auth->flags & AU_SECURE) ||
    22.7 +#ifdef QMAIL
    22.8 +	       getenv("INTRANET") ||
    22.9 +#endif
   22.10  	       !mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL))) ?
   22.11  	(*auth->server) (resp,argc,argv) : NIL;
   22.12    return NIL;			/* no authenticator found */
    23.1 --- a/src/c-client/mail.h	Mon Sep 14 15:17:45 2009 +0900
    23.2 +++ b/src/c-client/mail.h	Mon Sep 14 19:23:11 2009 +0900
    23.3 @@ -858,6 +858,7 @@
    23.4    unsigned int spare7 : 1;	/* seventh spare bit */
    23.5    unsigned int spare8 : 1;	/* eighth spare bit */
    23.6    void *sparep;			/* spare pointer */
    23.7 +  void *maildirp;		/* for the Maildir driver */
    23.8    unsigned long user_flags;	/* user-assignable flags */
    23.9  } MESSAGECACHE;
   23.10  
    24.1 --- a/src/imapd/imapd.c	Mon Sep 14 15:17:45 2009 +0900
    24.2 +++ b/src/imapd/imapd.c	Mon Sep 14 19:23:11 2009 +0900
    24.3 @@ -553,6 +553,9 @@
    24.4  
    24.5  				/* plaintext login with password */
    24.6  	else if (!strcmp (cmd,"LOGIN")) {
    24.7 +          #ifdef QMAIL
    24.8 +          extern char* conv_virtualdomain(char*);
    24.9 +          #endif
   24.10  	  if (user) fs_give ((void **) &user);
   24.11  	  if (pass) fs_give ((void **) &pass);
   24.12  				/* two arguments */
   24.13 @@ -573,7 +576,11 @@
   24.14  	  else {		/* delimit user from possible admin */
   24.15  	    if (s = strchr (user,'*')) *s++ ='\0';
   24.16  				/* see if username and password are OK */
   24.17 +#ifdef QMAIL
   24.18 +	    if (server_login (conv_virtualdomain(user),pass,s,argc,argv)) {
   24.19 +#else
   24.20  	    if (server_login (user,pass,s,argc,argv)) {
   24.21 +#endif
   24.22  	      state = SELECT;	/* make select */
   24.23  	      alerttime = 0;	/* force alert */
   24.24  	      response = logwin;/* return logged-in capabilities */
    25.1 --- a/src/ipopd/ipop3d.c	Mon Sep 14 15:17:45 2009 +0900
    25.2 +++ b/src/ipopd/ipop3d.c	Mon Sep 14 19:23:11 2009 +0900
    25.3 @@ -96,6 +96,9 @@
    25.4  void trmint ();
    25.5  int pass_login (char *t,int argc,char *argv[]);
    25.6  char *apop_login (char *chal,char *user,char *md5,int argc,char *argv[]);
    25.7 +#ifdef QMAIL
    25.8 +char* conv_virtualdomain(char *account);
    25.9 +#endif
   25.10  char *responder (void *challenge,unsigned long clen,unsigned long *rlen);
   25.11  int mbxopen (char *mailbox);
   25.12  long blat (char *text,long lines,unsigned long size,STRING *st);
   25.13 @@ -128,7 +131,11 @@
   25.14      AUTHENTICATOR *auth = mail_lookup_auth (1);
   25.15      while (auth && compare_cstring (auth->name,"CRAM-MD5")) auth = auth->next;
   25.16  				/* build challenge -- less than 128 chars */
   25.17 +#ifndef QMAIL
   25.18 +    if (!(auth->flags & AU_DISABLE))
   25.19 +#else
   25.20      if (auth && auth->server && !(auth->flags & AU_DISABLE))
   25.21 +#endif
   25.22        sprintf (challenge,"<%lx.%lx@%.64s>",(unsigned long) getpid (),
   25.23  	       (unsigned long) time (0),tcp_serverhost ());
   25.24      else challenge[0] = '\0';	/* no MD5 authentication */
   25.25 @@ -258,10 +265,17 @@
   25.26  				/* get user name */
   25.27  	    if (!(t && *t && (s = strtok (t," ")) && (t = strtok(NIL,"\012"))))
   25.28  	      PSOUT ("-ERR Missing APOP argument\015\012");
   25.29 -	    else if (!(user = apop_login (challenge,s,t,argc,argv)))
   25.30 -	      PSOUT ("-ERR Bad APOP\015\012");
   25.31 -	    else if ((state = mbxopen ("INBOX")) == TRANSACTION)
   25.32 -	      syslog (LOG_INFO,"APOP user=%.80s host=%.80s nmsgs=%lu/%lu",
   25.33 + #ifdef QMAIL
   25.34 +	    else if (!(user = apop_login (challenge,conv_virtualdomain(s),t,argc,argv))) {
   25.35 + #else /* !QMAIL */
   25.36 +	      else if (!(user = apop_login (challenge,s,t,argc,argv))) {
   25.37 + #endif /* QMAIL */
   25.38 +	      PSOUT ("-ERR Bad APOP (Maybe your password is expired)\015\012");
   25.39 +	      user = cpystr (s);
   25.40 +              syslog (LOG_INFO,"APOP login failure user=%.80s host=%.80s",
   25.41 +                    user,tcp_clienthost ());
   25.42 +	    } else if ((state = mbxopen ("INBOX")) == TRANSACTION)
   25.43 +	      syslog (LOG_INFO,"APOP user=%.80s host=%.80s nmsgs=%ld/%ld",
   25.44  		      user,tcp_clienthost (),nmsgs,stream->nmsgs);
   25.45  	    else syslog (LOG_INFO,"APOP user=%.80s host=%.80s no mailbox",
   25.46  			 user,tcp_clienthost ());
   25.47 @@ -279,8 +293,20 @@
   25.48  	  }
   25.49  	  else PSOUT ("+OK STLS completed\015\012");
   25.50  	}
   25.51 +#ifndef RESTRICT_POP
   25.52  	else if (!mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL) &&
   25.53  		 !strcmp (s,"USER")) {
   25.54 +#else	/* !RESTRICT_POP */
   25.55 +	else if (!strcmp (s,"USER")) {
   25.56 +	  if (getenv("INTRANET") == NIL) {
   25.57 +	    PSOUT("-ERR Sorry, we don't allow POP3 from your network.  Use APOP instead.\015\012");
   25.58 +	    user = cpystr(t);
   25.59 +	    syslog (LOG_INFO,"Plain POP3 is restricted user=%.80s host=%.80s",
   25.60 +		    user,tcp_clienthost ());
   25.61 +	    memset(user, '\0', strlen(user));
   25.62 +	    break;
   25.63 +	  }
   25.64 +#endif
   25.65  	  if (host) fs_give ((void **) &host);
   25.66  	  if (user) fs_give ((void **) &user);
   25.67  	  if (pass) fs_give ((void **) &pass);
   25.68 @@ -294,7 +320,11 @@
   25.69  	      user = cpystr (s);/* copy user name */
   25.70  	    }
   25.71  				/* local user name */
   25.72 +#ifdef QMAIL
   25.73 +	    else user = conv_virtualdomain(cpystr (t));
   25.74 +#else
   25.75  	    else user = cpystr (t);
   25.76 +#endif
   25.77  	    PSOUT ("+OK User name accepted, password please\015\012");
   25.78  	  }
   25.79  	  else PSOUT ("-ERR Missing username argument\015\012");
    26.1 --- a/src/osdep/unix/Makefile	Mon Sep 14 15:17:45 2009 +0900
    26.2 +++ b/src/osdep/unix/Makefile	Mon Sep 14 19:23:11 2009 +0900
    26.3 @@ -27,7 +27,7 @@
    26.4  # Command line build parameters
    26.5  
    26.6  EXTRAAUTHENTICATORS=
    26.7 -EXTRADRIVERS=mbox
    26.8 +EXTRADRIVERS=maildir mbox
    26.9  PASSWDTYPE=std
   26.10  SSLTYPE=nopwd
   26.11  IP=4
   26.12 @@ -102,6 +102,7 @@
   26.13  NEWSSPOOL=$(SPOOLDIR)/news
   26.14  RSHPATH=/usr/ucb/rsh
   26.15  MD5PWD=/etc/cram-md5.pwd
   26.16 +MD5CFLAGS= -DAPOPOPEN=\"/usr/local/sbin/deapop\" -DUSERAPOPFILE=\".apop\" -DPOPBEFORESMTP -DPOP3RECORDER=\"/usr/local/etc/pop3-record\"
   26.17  # Tries one of the test alternatives below if not specified.
   26.18  LOCKPGM=
   26.19  # Test alternatives if LOCKPGM not specified
   26.20 @@ -144,17 +145,21 @@
   26.21  # However, mh needs to be before any sysinbox formats (such as mmdf or unix)
   26.22  # since otherwise INBOX won't work correctly when mh_allow_inbox is set.
   26.23  #
   26.24 -DEFAULTDRIVERS=imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile
   26.25 +DEFAULTDRIVERS=maildir imap nntp pop3 mix mx mbx tenex mtx mh mmdf unix news phile
   26.26  CHUNKSIZE=65536
   26.27  
   26.28  # Normally no need to change any of these
   26.29 +EXTRACFLAGS=-DQMAIL
   26.30 +# Next variable controls default maildir when user has no ~/.qmail
   26.31 +#MAILDIRCFLAGS=-DDEFAULTMAILDIR="maildir" -DQMAILCONTROL="/var/qmail/control"
   26.32 +MAILDIRCFLAGS=-DQMAILCONTROL="/var/qmail/control"
   26.33  
   26.34  ARCHIVE=c-client.a
   26.35  BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o utf8aux.o siglocal.o \
   26.36   dummy.o pseudo.o netmsg.o flstring.o fdstring.o \
   26.37   rfc822.o nntp.o smtp.o imap4r1.o pop3.o \
   26.38 - unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o mix.o
   26.39 -CFLAGS=-g
   26.40 + unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o mix.o maildir.o
   26.41 +CFLAGS=-g $(EXTRACFLAGS)
   26.42  
   26.43  CAT=cat
   26.44  MAKE=make
   26.45 @@ -892,6 +897,7 @@
   26.46  unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h
   26.47  utf8.o: mail.h misc.h osdep.h utf8.h tmap.c widths.c
   26.48  utf8aux.o: mail.h misc.h osdep.h utf8.h
   26.49 +maildir.o: mail.h misc.h osdep.h maildir.h dummy.h
   26.50  
   26.51  
   26.52  # OS-dependent
   26.53 @@ -960,6 +966,7 @@
   26.54  	@echo Once-only environment setup...
   26.55  	echo $(CC) > CCTYPE
   26.56  	echo $(BASECFLAGS) '$(EXTRACFLAGS)' -DCHUNKSIZE=$(CHUNKSIZE) > CFLAGS
   26.57 +	echo '$(MAILDIRCFLAGS)' >> CFLAGS
   26.58  	echo -DCREATEPROTO=$(CREATEPROTO) -DEMPTYPROTO=$(EMPTYPROTO) \
   26.59  	 -DMD5ENABLE=\"$(MD5PWD)\" -DMAILSPOOL=\"$(MAILSPOOL)\" \
   26.60  	 -DANONYMOUSHOME=\"$(MAILSPOOL)/anonymous\" \
   26.61 @@ -967,6 +974,7 @@
   26.62  	 -DRSHPATH=\"$(RSHPATH)\" -DLOCKPGM=\"$(LOCKPGM)\" \
   26.63  	 -DLOCKPGM1=\"$(LOCKPGM1)\" -DLOCKPGM2=\"$(LOCKPGM2)\" \
   26.64  	 -DLOCKPGM3=\"$(LOCKPGM3)\" > OSCFLAGS
   26.65 +	echo $(MD5CFLAGS) >> OSCFLAGS
   26.66  	echo $(BASELDFLAGS) $(EXTRALDFLAGS) > LDFLAGS
   26.67  	echo "$(ARRC) $(ARCHIVE) $(BINARIES);$(RANLIB) $(ARCHIVE)" > ARCHIVE
   26.68  	echo $(OS) > OSTYPE
    27.1 --- a/src/osdep/unix/env_unix.c	Mon Sep 14 15:17:45 2009 +0900
    27.2 +++ b/src/osdep/unix/env_unix.c	Mon Sep 14 19:23:11 2009 +0900
    27.3 @@ -422,6 +422,10 @@
    27.4    case SET_DISABLEPLAINTEXT:
    27.5      disablePlaintext = (long) value;
    27.6    case GET_DISABLEPLAINTEXT:
    27.7 +#ifdef RESTRICT_POP
    27.8 +    if (getenv("INTRANET") == NIL) disablePlaintext = 1;
    27.9 +    else disablePlaintext = NIL;
   27.10 +#endif
   27.11      ret = (void *) disablePlaintext;
   27.12      break;
   27.13    case SET_CHROOTSERVER:
   27.14 @@ -665,6 +669,7 @@
   27.15    char *s;
   27.16    struct passwd *pw;
   27.17    struct passwd *ret = NIL;
   27.18 +#ifndef QMAIL	/* imapext md5 checker run previously. no need to do here */
   27.19    if (auth_md5.server) {	/* using CRAM-MD5 authentication? */
   27.20      if (s = auth_md5_pwd (user)) {
   27.21        if (!strcmp (s,pwd) || ((*pwd == ' ') && pwd[1] && !strcmp (s,pwd+1)))
   27.22 @@ -673,7 +678,9 @@
   27.23        fs_give ((void **) &s);
   27.24      }
   27.25    }
   27.26 -  else if (pw = pwuser (user)) {/* can get user? */
   27.27 +  else
   27.28 +#endif
   27.29 +  if (pw = pwuser (user)) {/* can get user? */
   27.30      s = cpystr (pw->pw_name);	/* copy returned name in case we need it */
   27.31      if (*pwd && !(ret = checkpw (pw,pwd,argc,argv)) &&
   27.32  	(*pwd == ' ') && pwd[1] && (ret = pwuser (s)))
   27.33 @@ -697,6 +704,10 @@
   27.34    struct passwd *pw = NIL;
   27.35    int level = LOG_NOTICE;
   27.36    char *err = "failed";
   27.37 +#ifdef QMAIL
   27.38 +  char usr[MAILTMPLEN], *apoppswd;
   27.39 +  strncpy(usr, user, MAILTMPLEN-1);
   27.40 +#endif
   27.41  				/* cretins still haven't given up */
   27.42    if ((strlen (user) >= NETMAXUSER) ||
   27.43        (authuser && (strlen (authuser) >= NETMAXUSER))) {
   27.44 @@ -706,6 +717,16 @@
   27.45    }
   27.46    else if (logtry-- <= 0) err = "excessive login failures";
   27.47    else if (disablePlaintext) err = "disabled";
   27.48 +#ifdef QMAIL
   27.49 +  else if ((logtry > 0) &&
   27.50 +            (apoppswd = auth_md5_pwd(usr))
   27.51 +           && !strcmp(apoppswd, pwd)
   27.52 +           && (pw = getpwnam(usr))) {
   27.53 +    memset(apoppswd, 0, strlen(apoppswd));
   27.54 +    fs_give((void**) &apoppswd);
   27.55 +    return pw_login(pw, usr, pw->pw_name, pw->pw_dir, argc, argv);
   27.56 +  }
   27.57 +#endif
   27.58    else if (!(authuser && *authuser)) pw = valpwd (user,pwd,argc,argv);
   27.59    else if (valpwd (authuser,pwd,argc,argv)) pw = pwuser (user);
   27.60    if (pw && pw_login (pw,authuser,pw->pw_name,NIL,argc,argv)) return T;
   27.61 @@ -728,6 +749,34 @@
   27.62    return pw_login (pwuser (user),authuser,user,NIL,argc,argv);
   27.63  }
   27.64  
   27.65 +void permitsmtp()	/* to update tcp permission */
   27.66 +{
   27.67 +#ifdef POPBEFORESMTP
   27.68 +  #include <sys/types.h>
   27.69 +  #include <sys/wait.h>
   27.70 +  #ifndef POP3RECORDER
   27.71 +  # define POP3RECORDER "/usr/local/etc/pop3-record"
   27.72 +  #endif
   27.73 +  int child;
   27.74 +  int wstat;
   27.75 +  char *permsmtp = POP3RECORDER;
   27.76 +
   27.77 +  switch(child = fork())
   27.78 +   {
   27.79 +    case -1:
   27.80 +	syslog (LOG_INFO,"Cannot exec %s", permsmtp);
   27.81 +	_exit(111);
   27.82 +	break;
   27.83 +    case 0:
   27.84 +	execl(permsmtp, permsmtp, 0);
   27.85 +	syslog (LOG_INFO,"Cannot exec %s", permsmtp);
   27.86 +	_exit(111); break;
   27.87 +   }
   27.88 +  waitpid(child, &wstat, 0);
   27.89 +#endif
   27.90 +}
   27.91 +
   27.92 +
   27.93  
   27.94  /* Log in as anonymous daemon
   27.95   * Accepts: argument count
   27.96 @@ -781,8 +830,14 @@
   27.97        else fatal ("Login failed after chroot");
   27.98      }
   27.99  				/* normal login */
  27.100 +#ifdef QMAIL
  27.101 +    else if (((pw->pw_uid == geteuid ()) || (permitsmtp(), loginpw (pw,argc,argv
  27.102 +))) &&
  27.103 +             (ret = env_init (user,home))) chdir (myhomedir ());
  27.104 +#else
  27.105      else if (((pw->pw_uid == geteuid ()) || loginpw (pw,argc,argv)) &&
  27.106 -	     (ret = env_init (user,home))) chdir (myhomedir ());
  27.107 +             (ret = env_init (user,home))) chdir (myhomedir ());
  27.108 +#endif
  27.109      fs_give ((void **) &home);	/* clean up */
  27.110      if (user) fs_give ((void **) &user);
  27.111    }
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/src/osdep/unix/maildir.c	Mon Sep 14 19:23:11 2009 +0900
    28.3 @@ -0,0 +1,1541 @@
    28.4 +/*
    28.5 + * Maildir Module for PINE 4.0x - fourth release, use with CARE! 
    28.6 + *
    28.7 + * Author:      Mattias Larsson <ml@techno.org>
    28.8 + *
    28.9 + * Version:     21.07.98
   28.10 + *
   28.11 + * Please read the README.maildir file before using this module!
   28.12 + *
   28.13 + * If you have any questions, please e-mail ml@techno.org 
   28.14 + *
   28.15 + * Multiple inboxes patch by Dean Gaudet <dgaudet@arctic.org>
   28.16 + *
   28.17 + * =================================================
   28.18 + *
   28.19 + * Based on the IMAP2 maildir routines by:
   28.20 + *
   28.21 + * Author:      Eric Green
   28.22 + *              Bloodhounds International Inc.
   28.23 + *              thrytis@imaxx.net
   28.24 + *
   28.25 + * Additional contributions from:
   28.26 + *              Aidas Kasparas (kaspar@soften.ktu.lt)
   28.27 + *
   28.28 + * Date:        27 April 1997
   28.29 + * Last Edited: 13 June 1997
   28.30 + *
   28.31 + * Based (heavily) on mh.c and other c-client library files by Mark Crispin:
   28.32 + *
   28.33 + *              Mark Crispin
   28.34 + *              Networks and Distributed Computing
   28.35 + *              Computing & Communications
   28.36 + *              University of Washington
   28.37 + *              Administration Building, AG-44
   28.38 + *              Seattle, WA  98195
   28.39 + *              Internet: MRC@CAC.Washington.EDU
   28.40 + *
   28.41 + * Copyright 1995 by the University of Washington
   28.42 + *
   28.43 + *  Permission to use, copy, modify, and distribute this software and its
   28.44 + * documentation for any purpose and without fee is hereby granted, provided
   28.45 + * that the above copyright notice appears in all copies and that both the
   28.46 + * above copyright notice and this permission notice appear in supporting
   28.47 + * documentation, and that the name of the University of Washington not be
   28.48 + * used in advertising or publicity pertaining to distribution of the software
   28.49 + * without specific, written prior permission.  This software is made
   28.50 + * available "as is", and
   28.51 + * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
   28.52 + * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
   28.53 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
   28.54 + * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
   28.55 + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
   28.56 + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
   28.57 + * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
   28.58 + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   28.59 + *
   28.60 + */
   28.61 +
   28.62 +/* CONFIGURABLE OPTIONS - PLEASE CHECK THESE OUT */
   28.63 +
   28.64 +#define NO_MAILDIR_FIDDLE	/* disallow Maildir with Maildir in the
   28.65 +				name. This is useful in an ISP setup
   28.66 +				using the IMAP daemon. #undef it if you
   28.67 +				are running a normal pine and know what
   28.68 +				you are doing */
   28.69 +
   28.70 +/* #define NO_ABSOLUTE_PATHS	/* if you define this, all paths
   28.71 +				use your HOMEDIR is the root instead
   28.72 +				of the actual root of the machine. This
   28.73 +				is also useful in an ISP setup with
   28.74 +				IMAP */
   28.75 +
   28.76 +#undef NO_UID_VALIDITIY		/* define this if you want the UID's not
   28.77 +				to be persistent over sessions. Use this
   28.78 +				if you use another client to read the
   28.79 +				maildir that screws up the special way
   28.80 +				in which we store UIDs. Do not enable
   28.81 +				unless you are sure you need it. */
   28.82 +	
   28.83 +/* END CONFIGURATION */
   28.84 +
   28.85 +#define MTA_DEBUG	/* debugging sent to stdout */
   28.86 +#undef MTA_DEBUG
   28.87 +
   28.88 +#include <stdio.h>
   28.89 +#include <ctype.h>
   28.90 +#include <errno.h>
   28.91 +extern int errno;		/* just in case */
   28.92 +#include "mail.h"
   28.93 +#include "osdep.h"
   28.94 +#include <pwd.h>
   28.95 +#include <sys/stat.h>
   28.96 +#include <sys/time.h>
   28.97 +#include <sys/types.h>
   28.98 +#include <dirent.h>
   28.99 +#include <utime.h>
  28.100 +#include "maildir.h"
  28.101 +#include "misc.h"
  28.102 +#include "dummy.h"
  28.103 +
  28.104 +/* Driver dispatch used by MAIL */
  28.105 +
  28.106 +DRIVER maildirdriver = {
  28.107 +  "maildir",			/* driver name */
  28.108 +				/* driver flags */
  28.109 +  DR_MAIL|DR_LOCAL|DR_NOFAST|DR_NAMESPACE,
  28.110 +  (DRIVER *) NIL,		/* next driver */
  28.111 +  maildir_valid,			/* mailbox is valid for us */
  28.112 +  maildir_parameters,		/* manipulate parameters */
  28.113 +  NIL,			/* scan mailboxes */
  28.114 +  maildir_list,			/* find mailboxes */
  28.115 +  maildir_lsub,			/* find subscribed mailboxes */
  28.116 +  maildir_sub,			/* subscribe to mailbox */
  28.117 +  maildir_unsub,		/* unsubscribe from mailbox */
  28.118 +  maildir_create,			/* create mailbox */
  28.119 +  maildir_delete,			/* delete mailbox */
  28.120 +  maildir_rename,			/* rename mailbox */
  28.121 +  NIL,				/* status of mailbox */
  28.122 +  maildir_open,			/* open mailbox */
  28.123 +  maildir_close,		/* close mailbox */
  28.124 +  maildir_fast,			/* fetch message "fast" attributes */
  28.125 +  NIL,				/* fetch message flags */
  28.126 +  NIL,				/* fetch overview */
  28.127 +  NIL,				/* fetch message envelopes */
  28.128 +  maildir_fetchheader,		/* fetch message header */
  28.129 +  maildir_fetchtext,		/* fetch message body */
  28.130 +  NIL,				/* fetch partial message text */
  28.131 +  NIL,				/* unique identifier */
  28.132 +  NIL,				/* message number */
  28.133 +  NIL,				/* modify flags */
  28.134 +  maildir_flagmsg,		/* per-message modify flags */
  28.135 +  NIL,				/* search for message based on criteria */
  28.136 +  NIL,				/* sort messages */
  28.137 +  NIL,				/* thread messages */
  28.138 +  maildir_ping,			/* ping mailbox to see if still alive */
  28.139 +  maildir_check,		/* check for new messages */
  28.140 +  maildir_expunge,			/* expunge deleted messages */
  28.141 +  maildir_copy,			/* copy messages to another mailbox */
  28.142 +  maildir_append,			/* append string message to mailbox */
  28.143 +  maildir_gc				/* garbage collect stream */
  28.144 +};
  28.145 +
  28.146 +				/* prototype stream */
  28.147 +MAILSTREAM maildirproto = {&maildirdriver};
  28.148 +
  28.149 +/* Check validity of mailbox
  28.150 + */
  28.151 + 
  28.152 +DRIVER *maildir_valid (char *name)
  28.153 +{
  28.154 +  return maildir_isvalid(name,T) ? &maildirdriver : NIL;
  28.155 +}
  28.156 +
  28.157 +int maildir_isvalid (char *name,long justname)
  28.158 +{
  28.159 +  char tmp[MAILTMPLEN];
  28.160 +  struct stat sbuf;
  28.161 +  
  28.162 +  if (!name || (!*name) || 
  28.163 +      ((*name == '#') && 
  28.164 +       (*(name+1) == 0 ||
  28.165 +	(*(name+1) != 'm' && *(name+1) != 'M') ||
  28.166 +	(*(name+2) != 'd' && *(name+1) != 'D') ||
  28.167 +	*(name+3) != '/')) || (*name == '.'))
  28.168 +    return NIL;
  28.169 +  
  28.170 +  /* okay, anything containing the name Maildir will be ignored
  28.171 +     this is to prevent anyone from fiddling with their incoming Maildir
  28.172 +     directly, it should be accessed via the INBOX alias */
  28.173 +
  28.174 +  #ifdef NO_MAILDIR_FIDDLE
  28.175 +  if (strstr(name, "Maildir")) {
  28.176 +	return NIL; 
  28.177 +	}
  28.178 +  #endif
  28.179 + 				/* If we are requested only to check 
  28.180 +  				   if the name is appropriate then we
  28.181 +  				   have done! */
  28.182 +  if (justname && *name == '#') return T;
  28.183 +  
  28.184 +
  28.185 +				/* must be valid local mailbox */
  28.186 +  if ((*name != '*') && (*name != '{') &&
  28.187 +      maildir_file (tmp,name) &&
  28.188 +				/* assume its maildir if its a dir */
  28.189 +      stat (tmp,&sbuf) == 0 && S_ISDIR (sbuf.st_mode))
  28.190 +    return T;
  28.191 +
  28.192 +				/* INBOX is for default Maildir */
  28.193 +  if (!strcmp (ucase (strncpy (tmp,name,MAILTMPLEN)), "INBOX") &&
  28.194 +      (stat (maildir_file (tmp,name),&sbuf) == 0) &&
  28.195 +      S_ISDIR (sbuf.st_mode))
  28.196 +    return T;
  28.197 +
  28.198 +  return NIL;
  28.199 +}
  28.200 +#ifdef QMAIL
  28.201 +#ifndef QMAILCONTROL
  28.202 +# define QMAILCONTROL "/var/qmail/control"
  28.203 +#endif
  28.204 +#ifndef DOTQMAIL
  28.205 +# ifdef POSTFIX
  28.206 +#  define DOTQMAIL ".forward"
  28.207 +# else
  28.208 +#  define DOTQMAIL ".qmail"
  28.209 +# endif
  28.210 +#endif
  28.211 +#ifndef XADDR_DELIM
  28.212 +# ifdef POSTFIX
  28.213 +#  define XADDR_DELIM "+"
  28.214 +# else
  28.215 +#  define XADDR_DELIM "-"
  28.216 +# endif
  28.217 +#endif
  28.218 +
  28.219 +/* Convert virtual domain user
  28.220 + */
  28.221 +char* conv_virtualdomain(char *account) {
  28.222 +  char *dom = strchr(account, '@'), *p;
  28.223 +  char vd[MAILTMPLEN+1], rewrite[MAILTMPLEN+1], previous[MAILTMPLEN+1];
  28.224 +  FILE *vdfd;
  28.225 +  int match=0;
  28.226 +  snprintf(vd, MAILTMPLEN, "%s/%s", QMAILCONTROL, "virtualdomains");
  28.227 +  if (NIL == dom) return account;
  28.228 +  dom++;		/* set position of domain part beginning */
  28.229 +  if (dom && NIL != (vdfd = fopen (vd, "r"))) {
  28.230 +    char buf[MAILTMPLEN+1], *s;
  28.231 +    int l = strlen(dom);
  28.232 +    int L = strlen(account);
  28.233 +    while ((s=fgets(buf, MAILTMPLEN, vdfd))) {
  28.234 +      if (p=strchr(s, '#'))
  28.235 +        *p = '\0';			/* zap comments */
  28.236 +      if (!strchr(buf, ':'))
  28.237 +        continue;
  28.238 +      while (s && (strrchr(s, '\n') || strrchr(s, '\r') || strrchr(s, ' ')))
  28.239 +        s[strlen(s)-1] = '\0';
  28.240 +      if (!strncmp(account, s, L) && s[L] == ':' && s[L+1]) { /* user matches */
  28.241 +	match = 3;
  28.242 +        snprintf(rewrite, MAILTMPLEN, "%s%s%s", s+L+1, XADDR_DELIM, account);
  28.243 +	break;
  28.244 +      }
  28.245 +      if (!strncmp(dom, s, l) && s[l] == ':' && s[l+1]) { /* domain matches */
  28.246 +        match = 2;
  28.247 +	snprintf(rewrite, MAILTMPLEN, "%s%s%s", s+l+1, XADDR_DELIM, account);
  28.248 +	continue;
  28.249 +      }
  28.250 +      if (match < 2 && s[0] == '.') { /* if domain described in wildcard */
  28.251 +        if (p=strchr(s, ':')) {
  28.252 +	  *p = '\0';
  28.253 +	  if (!strcmp(dom+(strlen(dom)-strlen(s)), s)) {
  28.254 +	    if (match == 0
  28.255 +	        || strlen(previous) < strlen(s)) {
  28.256 +	      match = 1;
  28.257 +	      strncpy(previous, s, MAILTMPLEN);
  28.258 +	      snprintf(rewrite, MAILTMPLEN, "%s%s%s", p+1, XADDR_DELIM, account);
  28.259 +	    }
  28.260 +	  }
  28.261 +	}
  28.262 +      }
  28.263 +    }
  28.264 +    fclose(vdfd);
  28.265 +    if (match) {
  28.266 +      p = strchr(rewrite, '@');
  28.267 +      /* fprintf(stderr, "m=%d, rwr=[%s]\n", match, rewrite); */
  28.268 +      if (p) {
  28.269 +        *p = '\0';
  28.270 +      }
  28.271 +      /* fprintf(stderr, "rwr=[%s]\n", rewrite); */
  28.272 +      s = cpystr(rewrite);
  28.273 +      memset(vd, 0, sizeof(vd));
  28.274 +      memset(rewrite, 0, sizeof(rewrite));
  28.275 +      memset(previous, 0, sizeof(previous));
  28.276 +      return s;
  28.277 +    }
  28.278 +  }
  28.279 +  return account; /* return itself */
  28.280 +}
  28.281 +/* -------------------------------------------------
  28.282 +   Qmail virtual domain hack ends
  28.283 +   ------------------------------------------------- */
  28.284 +#endif
  28.285 +
  28.286 +char *maildir_getmaildir() {
  28.287 +  static char dir[MAILTMPLEN];
  28.288 +  extern char *mymailsuffix();
  28.289 +  static char qfile[MAILTMPLEN];
  28.290 +  FILE *qmail;
  28.291 +  dir[0] = '\0';
  28.292 +  snprintf(qfile, MAILTMPLEN, "%s/%s", myhomedir(), DOTQMAIL);
  28.293 +  strncat(qfile, mymailsuffix(), MAILTMPLEN);
  28.294 +  qmail = fopen(qfile, "r");
  28.295 +  if (NULL != qmail) {	/* if ~/.qmail file exists */
  28.296 +    char buf[MAILTMPLEN], *s;
  28.297 +    while ((s=fgets(buf, MAILTMPLEN, qmail))) {
  28.298 +	/* Skip preceding spaces and trailing newlines */
  28.299 +	while (*s && (*s == ' ' || *s == '\t')) {s++;}
  28.300 +	while (*s && (s[strlen(s)-1] == '\r' || s[strlen(s)-1] == '\n')) {
  28.301 +	s[strlen(s)-1] = '\0';
  28.302 +	}
  28.303 +	if (*s == '#') continue;
  28.304 +	if (s[strlen(s)-1] != '/') continue; /* Skip non maildir format */
  28.305 +        if (*s == '~' && *(s+1) == '/')
  28.306 +            *s = '.';           /* Convert `~/' to `./' (for Postfix) */
  28.307 +	strncpy(dir, s, MAILTMPLEN);
  28.308 +        break;
  28.309 +    }
  28.310 +    fclose(qmail);
  28.311 +  }
  28.312 +#ifdef DEFAULTMAILDIR
  28.313 +  else {
  28.314 +    strncpy(dir, DEFAULTMAILDIR, MAILTMPLEN);
  28.315 +  }
  28.316 +#endif
  28.317 +  if (dir[0]) {
  28.318 +    return dir;
  28.319 +  } else {
  28.320 +#ifdef DEFAULTMAILDIR
  28.321 +    snprintf(dir, MAILTMPLEN, "%s/%s/", myhomedir(), DEFAULTMAILDIR);
  28.322 +#else
  28.323 +    snprintf(dir, MAILTMPLEN, "%s/%s/", myhomedir(), MAILDIRPATH);
  28.324 +#endif
  28.325 +    return dir;
  28.326 +  }
  28.327 +}
  28.328 +
  28.329 +/* Maildir mail generate file string
  28.330 + */
  28.331 +
  28.332 +char *maildir_file (char *dst,char *name)
  28.333 +{
  28.334 +  char tmp[MAILTMPLEN];
  28.335 +  
  28.336 +  if (strlen (name) > 3 &&	/* safe do other comparisons */
  28.337 +      (*name == '#') &&
  28.338 +      (name[1] == 'm' || name[1] == 'M') &&
  28.339 +      (name[2] == 'd' || name[2] == 'D') &&
  28.340 +      (name[3] == '/'))
  28.341 +    name += 4;
  28.342 +
  28.343 +#ifdef NO_ABSOLUTE_PATHS  
  28.344 +  if (*name == '/') {	
  28.345 +  /* we do not want to accept / absolute paths, so lets strip the first
  28.346 +     / ... */
  28.347 +    snprintf(dst, MAILTMPLEN, "%s/%s/cur", myhomedir(), name+1);
  28.348 +
  28.349 +/*    strncpy (dst, name, MAILTMPLEN - 2);
  28.350 +    strncat (dst, "/cur", MAILTMPLEN - 2);
  28.351 +    dst[MAILTMPLEN - 1] = '\0'; */
  28.352 +  }
  28.353 +  else
  28.354 +    snprintf (dst, MAILTMPLEN, "%s/%s/cur",myhomedir (),
  28.355 +	    strcmp (ucase (strcnpy (tmp, name, MAILTMPLEN)), "INBOX") ? name : maildir_getmaildir());
  28.356 +#else
  28.357 +  if (*name == '/') {	
  28.358 +    strncpy (dst, name, MAILTMPLEN - 2);
  28.359 +    strncat (dst, "/cur", MAILTMPLEN - 2);
  28.360 +    dst[MAILTMPLEN - 1] = '\0';
  28.361 +  }
  28.362 +  else {
  28.363 +      char *maildir = maildir_getmaildir();
  28.364 +      if (*maildir == '/') {
  28.365 +          snprintf (dst,MAILTMPLEN,"%scur",maildir);
  28.366 +      } else {
  28.367 +          snprintf (dst,MAILTMPLEN,"%s/%s/cur",myhomedir (),
  28.368 +                   strcmp (ucase (strncpy (tmp, name, MAILTMPLEN)), "INBOX") ? name : maildir);
  28.369 +      }
  28.370 +  }
  28.371 +
  28.372 +#endif 
  28.373 +  
  28.374 +  #ifdef MTA_DEBUG
  28.375 +  printf("maildir_file '%s'\n", dst);
  28.376 +  #endif
  28.377 +  return dst;
  28.378 +}
  28.379 +
  28.380 +/* Maildir open
  28.381 + */
  28.382 + 
  28.383 +MAILSTREAM *maildir_open (MAILSTREAM *stream)
  28.384 +{
  28.385 + char tmp[MAILTMPLEN],tmp2[MAILTMPLEN];
  28.386 +
  28.387 + if (!stream) return &maildirproto;
  28.388 + if (LOCAL) {		/* recycle stream */
  28.389 +	maildir_close (stream, 0);
  28.390 +	stream->dtb = &maildirdriver;
  28.391 +	mail_free_cache (stream);
  28.392 +	stream->uid_last = 0;       /* default UID validity */
  28.393 +	stream->uid_validity = time (0);
  28.394 +	}
  28.395 +
  28.396 +	stream->uid_validity = 0; /* was time(0) */
  28.397 +
  28.398 +  if (stream->uid_last < time(0))
  28.399 +  	stream->uid_last = time (0);  
  28.400 +  
  28.401 +    stream->local = fs_get (sizeof (MAILDIRLOCAL));
  28.402 +  LOCAL->inbox = !strcmp (ucase (strncpy (tmp,stream->mailbox,MAILTMPLEN)),"INBOX") ||
  28.403 +      !strcmp (stream->mailbox,maildir_file (tmp2,"INBOX"));
  28.404 +  LOCAL->dir = cpystr (maildir_file (tmp,stream->mailbox)); /* copy dir name */
  28.405 +                                /* make temporary buffer */
  28.406 +  LOCAL->buf = (char *) fs_get ((LOCAL->buflen = CHUNKSIZE-1) + 1);
  28.407 +  LOCAL->scantime = 0;          /* not scanned yet */
  28.408 +  stream->sequence++;
  28.409 +  stream->nmsgs = stream->recent = 0;
  28.410 +
  28.411 +  maildir_ping_core (stream);
  28.412 +  maildir_ping (stream);
  28.413 +/*  if (maildir_ping (stream) && !(stream->nmsgs || stream->silent))
  28.414 +    printf("Mailbox is empty\n");
  28.415 +*/
  28.416 +  return stream;
  28.417 +
  28.418 +}
  28.419 +
  28.420 +/* Maildir ping mailbox
  28.421 + */
  28.422 +
  28.423 +long maildir_ping_core (MAILSTREAM *stream)
  28.424 +{
  28.425 +  char tmp[MAILTMPLEN];
  28.426 +  MESSAGECACHE *elt;
  28.427 +  struct stat sbuf, sbuf2;
  28.428 +  DIR *dir;
  28.429 +  struct direct *d;
  28.430 +  int reloadall = NIL;
  28.431 +  int uidinvalid = NIL;
  28.432 +  unsigned long old;
  28.433 +  long i;
  28.434 +  long nmsgs = stream->nmsgs;
  28.435 +  long recent = stream->recent;
  28.436 +  long nfiles = stream->nmsgs;
  28.437 +  int silent = stream->silent;
  28.438 +  char *s, *s2;
  28.439 +  mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL);
  28.440 +
  28.441 +/*  maildir_copynew (LOCAL->dir);
  28.442 + */
  28.443 +  
  28.444 +  if (stat (LOCAL->dir,&sbuf) < 0) {
  28.445 +    snprintf (tmp,MAILTMPLEN,"Unable to open maildir: %s",strerror (errno));
  28.446 +    mm_log (tmp,ERROR);
  28.447 +    return NIL;
  28.448 +  }
  28.449 +
  28.450 +  /* okay, lets try to figure out the Maildir UID validity. This is done
  28.451 +     by checking the last modification time of the file .uidvalidity
  28.452 +     in the rootdir of the Maildir. Any program reordering the files
  28.453 +     in the directory have to touch this file */
  28.454 +
  28.455 +  snprintf(tmp, MAILTMPLEN, "%s/../.uidvalidity", LOCAL->dir);
  28.456 +  
  28.457 +  if (stat (tmp,&sbuf2) < 0) {
  28.458 +	/* no uid validity file found, if uid_validity == 0, we have
  28.459 +	   to set it to something other than 0, and then create the
  28.460 +	   .uidvalidity file for future accesses */
  28.461 +
  28.462 +	if (stream->uid_validity == 0) {
  28.463 +		FILE *fl;
  28.464 +		struct utimbuf tbuf;
  28.465 +		
  28.466 +		stream->uid_validity = time(0);
  28.467 +		tbuf.actime = stream->uid_validity;
  28.468 +		tbuf.modtime = stream->uid_validity;
  28.469 +
  28.470 +		if ((fl = fopen(tmp, "w"))) {
  28.471 +			fclose(fl);
  28.472 +			chmod (tmp, S_IRUSR|S_IWUSR);
  28.473 +			utime(tmp, &tbuf);
  28.474 +			}
  28.475 +		}
  28.476 +		uidinvalid = T; /* UID's are invalid, update them */
  28.477 +	} else {
  28.478 +	/* valid file, lets set UID if uid_validity = 0 */
  28.479 +	if (stream->uid_validity == 0) {
  28.480 +	stream->uid_validity = sbuf2.st_mtime;
  28.481 +		}
  28.482 +	}
  28.483 +
  28.484 +  #ifdef NO_UID_VALIDITY
  28.485 +  uidinvalid = T; /* force the UIDs to be invalid and reset every time,
  28.486 +  		     useful in an environment without imap servers and
  28.487 +  		     clients that screw up the UIDs.. i'd leave it to
  28.488 +  		     OFF until I really need it though... */
  28.489 +  #endif
  28.490 +
  28.491 +  stream->silent = T;  
  28.492 +  if (sbuf.st_ctime != LOCAL->scantime) {
  28.493 +    /* update the message list */
  28.494 +    /* int maildir_namesort(const void *,const void *);
  28.495 +       int (*mn)(struct direct **, struct direct **) = maildir_namesort; */
  28.496 +    struct direct **names = NIL;
  28.497 +    nfiles = scandir (LOCAL->dir,&names,maildir_select,maildir_namesort);
  28.498 +
  28.499 +    for (i = 0; i < nfiles; i++) {
  28.500 +
  28.501 +	/* check if file has executable bit set */
  28.502 +	snprintf(tmp, MAILTMPLEN, "%s/%s", LOCAL->dir, names[i]->d_name);
  28.503 +  	stat (tmp,&sbuf2);
  28.504 +	if (sbuf2.st_mode & S_IXUSR) {
  28.505 +		/* executable bit set, modtime is uid */
  28.506 +		if (sbuf2.st_mtime > stream->uid_last)
  28.507 +			stream->uid_last = sbuf2.st_mtime+1;
  28.508 +		}
  28.509 +	/* this is kept for backwards compatibility */
  28.510 +        if ((s = strstr (names[i]->d_name,":3,")))
  28.511 +		s += 3;
  28.512 +        if (s && (s2 = strstr (s, ",U"))) {
  28.513 +      		s2 += 2;
  28.514 +		sscanf(s2, "%d", &old);
  28.515 +		if (old > stream->uid_last) {
  28.516 +			stream->uid_last = old+1;
  28.517 +			}
  28.518 +		}	
  28.519 +	
  28.520 +    }
  28.521 +
  28.522 +    mm_critical (stream);	/* go critical */
  28.523 +    old = stream->uid_last;
  28.524 +    LOCAL->scantime = sbuf.st_ctime;
  28.525 +
  28.526 +				/* check if old files same */
  28.527 +    for (i = 0; i < stream->nmsgs; i++) {
  28.528 +
  28.529 +      if (strcmp ((char *) mail_elt (stream, i + 1)->maildirp,
  28.530 +		  names[i]->d_name)) {
  28.531 +	reloadall = T;
  28.532 +	break;
  28.533 +      }
  28.534 +    }
  28.535 +
  28.536 +    if (reloadall) { /* files are out of order, rebuild cache */
  28.537 +
  28.538 +      i = 1;
  28.539 +      while (i <= stream->nmsgs)
  28.540 +				/* clean out cache */
  28.541 +	if ((elt = (MESSAGECACHE *) (*mc) (stream,i,CH_ELT))) {
  28.542 +	  fs_give ((void **) &elt->maildirp);
  28.543 +	  mail_expunged (stream,i);
  28.544 +	}
  28.545 +	else
  28.546 +	  i++;
  28.547 +      
  28.548 +      mm_log ("Warning: Mailbox has changed in an unexpected way.  Reloading.",
  28.549 +	      WARN);
  28.550 +      stream->nmsgs = 0;
  28.551 +    }
  28.552 +    nmsgs = stream->nmsgs;
  28.553 +    
  28.554 +    stream->nmsgs = nfiles; /* hm? */    
  28.555 +
  28.556 +    for (i = nmsgs; i < nfiles; i++) {
  28.557 +
  28.558 +      mail_exists(stream, i+1);
  28.559 +				/* if newly seen, add to list */
  28.560 +      (elt = mail_elt (stream, i + 1))->maildirp = (long) cpystr (names[i]->d_name);
  28.561 +       elt->valid = T;
  28.562 +
  28.563 +      /* grab the flags */
  28.564 +      if ((s = strstr (names[i]->d_name,":3,"))) {
  28.565 +	s += 3;
  28.566 +	if (strchr (s,'F'))
  28.567 +	  elt->flagged = T;
  28.568 +	if (strchr (s,'R'))
  28.569 +	  elt->answered = T;
  28.570 +	if (strchr (s,'S'))
  28.571 +	  elt->seen = T;
  28.572 +	if (strchr (s,'T'))
  28.573 +	  elt->deleted = T;
  28.574 +      } else if ((s = strstr (names[i]->d_name,":2,"))) {
  28.575 +	/* this is the :2, id where all files go nowadays */
  28.576 +	s += 3;
  28.577 +	if (strchr (s,'F'))
  28.578 +	  elt->flagged = T;
  28.579 +	if (strchr (s,'R'))
  28.580 +	  elt->answered = T;
  28.581 +	if (strchr (s,'S'))
  28.582 +	  elt->seen = T;
  28.583 +	if (strchr (s,'T'))
  28.584 +	  elt->deleted = T;
  28.585 +	snprintf(tmp, MAILTMPLEN, "%s/%s", LOCAL->dir, names[i]->d_name);
  28.586 +  	stat (tmp,&sbuf2);
  28.587 +	if (sbuf2.st_mode & S_IXUSR) {
  28.588 +		/* executable bit set, modtime is uid */
  28.589 +		elt->private.uid = sbuf2.st_mtime;
  28.590 +		}
  28.591 +	/* and if we could not retrieve UID from modtime, or if
  28.592 +	   UIDs are invalid, go here */
  28.593 +	if (elt->private.uid == 0 || uidinvalid) {
  28.594 +        	stream->uid_last = (elt = mail_elt (stream,i+1))->private.uid = stream->uid_last+1;
  28.595 +		maildir_flagmsg(stream, elt);
  28.596 +		}	
  28.597 +	s = 0; /* make sure next if statement does not trigger */      
  28.598 +      	}
  28.599 +
  28.600 +      if (s)
  28.601 +      if ((s2 = strstr (s, ",U"))) {
  28.602 +      	s2 += 2;
  28.603 +	sscanf(s2, "%d", &elt->private.uid);
  28.604 +	if (elt->private.uid == 0 || uidinvalid) {
  28.605 +        	stream->uid_last = (elt = mail_elt (stream,i+1))->private.uid = stream->uid_last+1;
  28.606 +		maildir_flagmsg(stream, elt);
  28.607 +		}	
  28.608 +	
  28.609 +      	} else { /* assign new UID */
  28.610 +        stream->uid_last = (elt = mail_elt (stream,i+1))->private.uid = stream->uid_last+1;
  28.611 +	elt->recent = T;
  28.612 +	recent++;
  28.613 +	maildir_flagmsg(stream, elt); /* store the UID that we assigned to it */
  28.614 +	}	
  28.615 +
  28.616 +
  28.617 +
  28.618 +    }
  28.619 +
  28.620 +    mm_nocritical (stream);	/* release critical */
  28.621 +				/* free the names stuff */
  28.622 +    for (i = 0; i < nfiles; i++)
  28.623 +      fs_give ((void **) &names[i]);
  28.624 +    if (names)
  28.625 +      fs_give ((void **) &names);
  28.626 +  }
  28.627 +  stream->silent = silent;
  28.628 +  mail_exists(stream,nfiles);
  28.629 +/*  if (!reloadall)  */
  28.630 +  	mail_recent (stream,recent);
  28.631 +
  28.632 +  return T;			/* return that we are alive */
  28.633 +}
  28.634 +
  28.635 +long maildir_ping (MAILSTREAM *stream)
  28.636 +{
  28.637 +  maildir_copynew (LOCAL->dir);
  28.638 +  return maildir_ping_core (stream);
  28.639 +}
  28.640 +
  28.641 +void maildir_copynew (const char *mailbox)
  28.642 +{
  28.643 +  char tmp[MAILTMPLEN],file[MAILTMPLEN],newfile[MAILTMPLEN];
  28.644 +  DIR *dir;
  28.645 +  struct dirent *d;
  28.646 +  struct stat sbuf;
  28.647 +  
  28.648 +  snprintf (tmp,MAILTMPLEN,"%s/../new",mailbox);
  28.649 +  if (!(dir = opendir (tmp)))
  28.650 +    return;
  28.651 +
  28.652 +  while (d = readdir (dir)) {
  28.653 +    if (d->d_name[0] == '.')
  28.654 +      continue;			/* skip .files */
  28.655 +
  28.656 +    snprintf (file,MAILTMPLEN,"%s/%s",tmp,d->d_name);
  28.657 +				/* make sure this is a normal file */
  28.658 +    if (stat (file,&sbuf) == 0 && S_ISREG (sbuf.st_mode)) {
  28.659 +      
  28.660 +      if (strstr (d->d_name,":3,")) /* this message already has flags */
  28.661 +	snprintf (newfile,MAILTMPLEN,"%s/%s",mailbox,d->d_name);
  28.662 +      else
  28.663 +	snprintf (newfile,MAILTMPLEN,"%s/%s:3,",mailbox,d->d_name);
  28.664 +      
  28.665 +				/* move the new mail to the cur dir */
  28.666 +      if (link (file,newfile) == -1)
  28.667 +	mm_log("Unable to read new mail!",WARN);
  28.668 +      else
  28.669 +	unlink (file);	
  28.670 +    }
  28.671 +  }
  28.672 +  closedir (dir);
  28.673 +}
  28.674 +
  28.675 +int maildir_select (struct direct *name)
  28.676 +{
  28.677 +  if (name->d_name[0] != '.')
  28.678 +    return T;
  28.679 +
  28.680 +  return NIL;
  28.681 +}
  28.682 +
  28.683 +/* int maildir_namesort (struct direct **d1,struct direct **d2) */
  28.684 +int maildir_namesort (const void *d1, const void *d2)
  28.685 +{
  28.686 +  return strcmp ((*(struct direct **)d1)->d_name,
  28.687 +                 (*(struct direct **)d2)->d_name);
  28.688 +}
  28.689 +
  28.690 +
  28.691 +/* Maildir garbage collect stream
  28.692 + */
  28.693 +
  28.694 +void maildir_gc (MAILSTREAM *stream,long gcflags)
  28.695 +{
  28.696 +  unsigned long i;
  28.697 +  
  28.698 +  if (gcflags & GC_TEXTS) {	/* garbage collect texts? */
  28.699 +				/* flush texts from cache */
  28.700 +/*    if (LOCAL->hdr) fs_give ((void **) &LOCAL->hdr);
  28.701 +//    if (stream->text) fs_give ((void **) &stream->text);
  28.702 +//    stream->msgno = 0;		invalidate stream text
  28.703 +*/
  28.704 +  }
  28.705 +}
  28.706 +
  28.707 +/* Maildir close
  28.708 + */
  28.709 +
  28.710 +void maildir_close (MAILSTREAM *stream, long options)
  28.711 +{
  28.712 +  MESSAGECACHE *elt;
  28.713 +  int i;
  28.714 +  mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL);
  28.715 + 
  28.716 +/*  CL_EXPUNGE OPTION SUPPORT HERE SOMEWHERE! */
  28.717 +				/* clean out the cached paths */
  28.718 +  for (i = 1; i <= stream->nmsgs; i++)
  28.719 +    if ((elt = (MESSAGECACHE *) (*mc) (stream,i,CH_ELT)) && elt->maildirp) {
  28.720 +      fs_give ((void **) &elt->maildirp);
  28.721 +      elt->maildirp = 0; /* otherwise pine coredumps */  
  28.722 +	}  
  28.723 +  
  28.724 +  if (LOCAL) {			/* only if a stream is open */
  28.725 +    if (LOCAL->dir) fs_give ((void **) &LOCAL->dir);
  28.726 +    maildir_gc (stream,GC_TEXTS); /* free local cache */
  28.727 +				/* free local scratch buffer */
  28.728 +    if (LOCAL->buf) fs_give ((void **) &LOCAL->buf);
  28.729 +				/* nuke the local data */
  28.730 +    fs_give ((void **) &stream->local);
  28.731 +    stream->dtb = NIL;		/* log out the DTB */
  28.732 +  }
  28.733 +}
  28.734 +
  28.735 +void maildir_check (MAILSTREAM *stream)
  28.736 +{
  28.737 +  /* Perhaps in the future this will preserve flags */
  28.738 +  if (maildir_ping (stream)) mm_log ("Check completed",(long) NIL);   
  28.739 +}
  28.740 +
  28.741 +long maildir_fetchtext (MAILSTREAM *stream,unsigned long msgno,STRING *bs, long flags)
  28.742 +{
  28.743 +  unsigned long i;
  28.744 +  MESSAGECACHE *elt;
  28.745 +                                /* UID call "impossible" */
  28.746 +  if (flags & FT_UID) return NIL;
  28.747 +  elt = mail_elt (stream,msgno);/* get elt */
  28.748 +                                /* snarf message if don't have it yet */
  28.749 +  if (!elt->private.msg.text.text.data) {
  28.750 +    maildir_fetchheader (stream,msgno,&i,flags);
  28.751 +    if (!elt->private.msg.text.text.data) return NIL;
  28.752 +  }
  28.753 +  if (!(flags & FT_PEEK)) {     /* mark as seen */
  28.754 +    mail_elt (stream,msgno)->seen = T;
  28.755 +    maildir_flagmsg (stream, mail_elt(stream,msgno));
  28.756 +    mm_flags (stream,msgno);
  28.757 +  }
  28.758 +  if (!elt->private.msg.text.text.data) return NIL;
  28.759 +  INIT (bs,mail_string,elt->private.msg.text.text.data,
  28.760 +        elt->private.msg.text.text.size);
  28.761 +  return T;
  28.762 +}
  28.763 +
  28.764 +
  28.765 +/* Maildir fetch message header
  28.766 + */
  28.767 +
  28.768 +char *maildir_fetchheader (MAILSTREAM *stream,unsigned long msgno,
  28.769 +		unsigned long *length, long flags)
  28.770 +{
  28.771 +  unsigned long i,hdrsize;
  28.772 +  int fd;
  28.773 +  char *t;
  28.774 +  char tmp[MAILTMPLEN];
  28.775 +  char *s,*b;
  28.776 +  struct stat sbuf;
  28.777 +  struct tm *tm;
  28.778 +  MESSAGECACHE *elt;
  28.779 +  *length = 0;                  /* default to empty */
  28.780 +  if (flags & FT_UID) return "";/* UID call "impossible" */
  28.781 +  elt = mail_elt (stream,msgno);/* get elt */
  28.782 +  if (!elt->private.msg.header.text.data) {
  28.783 +
  28.784 +/*    maildir_gc (stream,GC_TEXTS);  invalidate current cache */
  28.785 +				/* build message file name */
  28.786 +    snprintf (tmp,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
  28.787 +    if ((fd = open (tmp,O_RDONLY,NIL)) >= 0) {
  28.788 +      fstat (fd,&sbuf);		/* get size of message */
  28.789 +				/* make plausible IMAPish date string */
  28.790 +      tm = gmtime (&sbuf.st_mtime);
  28.791 +      elt->day = tm->tm_mday; elt->month = tm->tm_mon + 1;
  28.792 +      elt->year = tm->tm_year + 1900 - BASEYEAR;
  28.793 +      elt->hours = tm->tm_hour; elt->minutes = tm->tm_min;
  28.794 +      elt->seconds = tm->tm_sec;
  28.795 +      elt->zhours = 0; elt->zminutes = 0;
  28.796 +				/* slurp message */
  28.797 +      read (fd,s = (char *) fs_get (sbuf.st_size + 1),sbuf.st_size);
  28.798 +      s[sbuf.st_size] = '\0';	/* tie off file */
  28.799 +      close (fd);		/* close file */
  28.800 +
  28.801 +      for (i = 0,b = s; *b && !(i && (*b == '\n')); i = (*b++ == '\n'));
  28.802 +      hdrsize = (*b ? ++b:b)-s;	/* number of header bytes */
  28.803 +
  28.804 +      elt->rfc822_size =          /* size of entire message in CRLF form */
  28.805 +       (elt->private.msg.header.text.size =
  28.806 +        strcrlfcpy ((char **) &elt->private.msg.header.text.data,&i,s,
  28.807 +                    hdrsize)) +
  28.808 +          (elt->private.msg.text.text.size =
  28.809 +           strcrlfcpy ((char **) &elt->private.msg.text.text.data,&i,b,
  28.810 +                       sbuf.st_size - hdrsize));
  28.811 +      fs_give ((void **) &s);
  28.812 +    } else return "";
  28.813 +
  28.814 +  }
  28.815 +
  28.816 +  *length = elt->private.msg.header.text.size;
  28.817 +  return (char *) elt->private.msg.header.text.data;
  28.818 +}
  28.819 +
  28.820 +void maildir_fast (MAILSTREAM *stream,char *sequence,long flags)
  28.821 +{
  28.822 +  unsigned long i,j;
  28.823 +				/* ugly and slow */
  28.824 +  if (stream && LOCAL && ((flags & FT_UID) ?
  28.825 +			  mail_uid_sequence (stream,sequence) :
  28.826 +			  mail_sequence (stream,sequence)))
  28.827 +    for (i = 1; i <= stream->nmsgs; i++)
  28.828 +      if (mail_elt (stream,i)->sequence) maildir_fetchheader (stream,i,&j,NIL);
  28.829 +}
  28.830 +
  28.831 +/* Maildir find list of subscribed mailboxes
  28.832 + * Accepts: mail stream
  28.833 + *	    pattern to search
  28.834 + */
  28.835 +
  28.836 +void maildir_list (MAILSTREAM *stream,char *ref, char *pat)
  28.837 +{
  28.838 +  DIR *dp;
  28.839 +  struct direct *d;
  28.840 +  struct stat sbuf;
  28.841 +  char *s,*s2,*cp,*np,curdir[MAILTMPLEN],name[MAILTMPLEN],subdir[MAILTMPLEN],rname[MAILTMPLEN];
  28.842 +
  28.843 +  strncpy(subdir, pat, MAILTMPLEN);
  28.844 +
  28.845 +  s = subdir;
  28.846 +  s2 = 0;
  28.847 +  while ((s = strstr(s, "/"))) {
  28.848 +  	s2 = s;
  28.849 +	s++;
  28.850 +	}
  28.851 +
  28.852 +  if (s2) { /* pointer to last / */
  28.853 +  	*s2 = '\0'; /* snip off string */
  28.854 +	s2++;
  28.855 +	/*syslog(LOG_INFO, "dir: '%s' pat: '%s'", subdir, s2);*/
  28.856 +  	snprintf(name, MAILTMPLEN, "%s/%s", myhomedir(), subdir);
  28.857 +	} else {
  28.858 +	s2 = pat;
  28.859 +	snprintf(name, MAILTMPLEN, "%s", myhomedir());
  28.860 +	strcpy(subdir, "");
  28.861 +	}
  28.862 +
  28.863 + maildir_listwork(name, stream, s2, subdir, 1);
  28.864 +
  28.865 + if (pmatch ("INBOX", pat))
  28.866 + 	mm_list (stream,NIL,"INBOX",LATT_NOINFERIORS);
  28.867 +
  28.868 +}
  28.869 +
  28.870 +void maildir_listwork(char *name1, MAILSTREAM *stream, char *s2, char *subdir, int flag)
  28.871 +{
  28.872 +  DIR *dp;
  28.873 +  struct direct *d;
  28.874 +  struct stat sbuf;
  28.875 +  char *s,*cp,*np,curdir[MAILTMPLEN],rname[MAILTMPLEN],name[MAILTMPLEN];
  28.876 +  char tmpdir[MAILTMPLEN];
  28.877 +  
  28.878 +  strncpy(name, name1, MAILTMPLEN);
  28.879 +  
  28.880 +  /*syslog(LOG_INFO, "opendir: '%s'", name);
  28.881 +  //syslog(LOG_INFO, "subdir: '%s'", subdir);
  28.882 +   */ 
  28.883 +  if (dp = opendir (name)) {	/* open directory */
  28.884 +    while (d = readdir (dp))	/* scan directory, ignore all . names */
  28.885 +      if (d->d_name[0] != '.' &&
  28.886 +	  strcmp(d->d_name, "Maildir")) {/* build file name */
  28.887 +	/* we do not want to list Maildir to customers, because
  28.888 +	   that might give them weird ideas :) */
  28.889 +
  28.890 +	if (subdir[0] != '\0' && subdir[0] != '%' && subdir[0] != '*')
  28.891 +		snprintf(name, MAILTMPLEN, "%s/%s", subdir, d->d_name);
  28.892 +	else
  28.893 +		snprintf(name, MAILTMPLEN, "%s", d->d_name);
  28.894 +	/*syslog(LOG_INFO, "ls: '%s'", name);*/
  28.895 +
  28.896 +	/* this matching might not be correctly implemented	*/
  28.897 +	if (maildir_file(curdir, name) &&
  28.898 +      		stat (curdir,&sbuf) == 0 && S_ISDIR (sbuf.st_mode)) {
  28.899 +		/*syslog(LOG_INFO, "here for some stange reason");*/
  28.900 +		if (pmatch(d->d_name, s2)) {
  28.901 +			mm_list (stream,'/',name,NIL);
  28.902 +			/* call function recursive if last char % */
  28.903 +			/*syslog(LOG_INFO, "s2: '%s'",s2);*/
  28.904 +			if (s2[strlen(s2)-1] == '%'
  28.905 +			||  s2[strlen(s2)-1] == '*') {
  28.906 +				snprintf(rname, MAILTMPLEN, "%s/%s", name1, name);
  28.907 +				/*syslog(LOG_INFO, "rname: '%s'", rname);*/
  28.908 +				maildir_listwork(rname, stream, "%", name, 1);
  28.909 +				}			
  28.910 +			}
  28.911 +		} else
  28.912 +	if (strlen(curdir) > 4 && pmatch(d->d_name, s2)) { 
  28.913 +  		int fnlen = strlen (curdir);
  28.914 +  		curdir[fnlen - 4] = '\0';
  28.915 +  		/*syslog(LOG_INFO, "fname: '%s'", curdir);*/
  28.916 +	if (stat (curdir,&sbuf) == 0 && S_ISDIR (sbuf.st_mode)) {
  28.917 +		/* okay, do not list with NoSelect, since Netscape
  28.918 +		   does not f*cking honor this flag.. stupid netscape */
  28.919 +		/*mm_list (stream,'/',name,LATT_NOSELECT);*/
  28.920 +
  28.921 +			/* call function recursive if last char % */
  28.922 +			/*syslog(LOG_INFO, "s2: '%s'",s2);*/
  28.923 +			if (s2[strlen(s2)-1] == '%' 
  28.924 +			||  s2[strlen(s2)-1] == '*') {
  28.925 +				snprintf(rname, MAILTMPLEN, "%s/%s", name1, name);
  28.926 +				/*syslog(LOG_INFO, "rname: '%s'", rname);*/
  28.927 +				maildir_listwork(rname, stream, "%", name, 1);
  28.928 +				}			
  28.929 +
  28.930 +		}
  28.931 +	    }
  28.932 +
  28.933 +	}
  28.934 +      closedir (dp);		/* all done, flush directory */
  28.935 +      }
  28.936 +
  28.937 +}
  28.938 +
  28.939 +
  28.940 +
  28.941 +
  28.942 +
  28.943 +void *maildir_parameters (long function,void *value)
  28.944 +{
  28.945 +  return NIL;
  28.946 +}
  28.947 +
  28.948 +long maildir_create (MAILSTREAM *stream,char *mailbox)
  28.949 +{
  28.950 +  char tmp[MAILTMPLEN];
  28.951 +  char err[MAILTMPLEN];
  28.952 +  char *s, *s2;
  28.953 +  int fnlen, i;
  28.954 +  char *subdir_names[] = {"/cur","/new","/tmp",NULL};
  28.955 +
  28.956 +				/* must not already exist */
  28.957 +  if (access (maildir_file (tmp,mailbox),F_OK) == 0) {
  28.958 +    snprintf (err,MAILTMPLEN,"Can't create mailbox %s: mailbox already exists",mailbox);
  28.959 +    mm_log (err,ERROR);
  28.960 +    return NIL;
  28.961 +  }
  28.962 +  
  28.963 +  maildir_file (tmp,mailbox);	/* get file name */
  28.964 +  fnlen = strlen (tmp);
  28.965 +  /*syslog(LOG_INFO, "fname: '%s'", tmp);*/
  28.966 +  tmp[fnlen - 4] = '\0';	/* making main directory's name */
  28.967 +  fnlen -= 4;
  28.968 +
  28.969 +  /* okay, try to add support for adding hiearchys of directories, this
  28.970 +     is done by scanning for /'s.... */
  28.971 +     
  28.972 +  /*syslog(LOG_INFO, "tmp '%s'", tmp);*/
  28.973 +  s = tmp;
  28.974 +
  28.975 +  while ((s = strstr(s, "/")) != 0) {
  28.976 +	/*syslog(LOG_INFO, "Before make: '%s'", s);*/
  28.977 +  	*s = '\0';
  28.978 +  	/*syslog(LOG_INFO, "Trying to make: '%s'", tmp);*/
  28.979 +	if (mkdir (tmp,0700) && *s != '\0') /* trying to make the dir */
  28.980 +	  if (errno != EEXIST) {
  28.981 +	    snprintf (err,MAILTMPLEN,"Can't create mailbox %s: %s %s",
  28.982 +		     mailbox,tmp,strerror (errno));
  28.983 +    	     mm_log (err,ERROR);
  28.984 +             return NIL;
  28.985 +	  }
  28.986 +  	*s = '/';
  28.987 +	s++;
  28.988 +  	} 
  28.989 +
  28.990 +  if (mkdir (tmp,0700)) {	/* try to make new dir */
  28.991 +    snprintf (err,MAILTMPLEN,"Can't create mailbox %s: %s %s",
  28.992 +	     mailbox,tmp,strerror (errno));
  28.993 +    mm_log (err,ERROR);
  28.994 +    return NIL;
  28.995 +  }
  28.996 +
  28.997 +  /*syslog(LOG_INFO, "create maildir");*/
  28.998 +  for (i = 0; subdir_names[i]; i++) {
  28.999 +    strncpy (tmp + fnlen,subdir_names[i],MAILTMPLEN);
 28.1000 +
 28.1001 +    if (mkdir (tmp,0700)) {	/* try to make new dir */
 28.1002 +      snprintf (err,MAILTMPLEN,"Can't create mailbox %s: %s %s",
 28.1003 +	       mailbox,tmp,strerror (errno));
 28.1004 +      mm_log (err,ERROR);
 28.1005 +      return NIL;
 28.1006 +    }
 28.1007 +  }
 28.1008 +
 28.1009 +  return T;			/* return success */
 28.1010 +}
 28.1011 +
 28.1012 +void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt)
 28.1013 +{
 28.1014 +  char oldfile[MAILTMPLEN],newfile[MAILTMPLEN],fn[MAILTMPLEN];
 28.1015 +  struct utimbuf tbuf;
 28.1016 +  char *s;
 28.1017 +
 28.1018 +                                /* build the new filename */
 28.1019 +  snprintf (oldfile,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
 28.1020 +  if ((s = strchr ((char *) elt->maildirp,':'))) *s = '\0';
 28.1021 +  snprintf (fn,MAILTMPLEN,"%s:2,%s%s%s%s",(char *) elt->maildirp,elt->flagged ? "F" : "",
 28.1022 +           elt->answered ? "R" : "",elt->seen ? "S" : "",
 28.1023 +           elt->deleted ? "T" : "");
 28.1024 +  snprintf (newfile,MAILTMPLEN,"%s/%s",LOCAL->dir,fn);
 28.1025 +                                /* rename the file with new flags */
 28.1026 +  if (rename (oldfile,newfile) < 0) {
 28.1027 +    snprintf(oldfile,MAILTMPLEN,"Unable to write flags to disk: %s",strerror (errno));
 28.1028 +    mm_log(oldfile,ERROR);
 28.1029 +    return;
 28.1030 +  }
 28.1031 +                                /* update the file name in cache */
 28.1032 +  fs_give ((void **) &elt->maildirp);
 28.1033 +  elt->maildirp = (long) cpystr (fn);
 28.1034 +
 28.1035 +  /* fix the UID on the file */
 28.1036 +  tbuf.actime = elt->private.uid;
 28.1037 +  tbuf.modtime = elt->private.uid;
 28.1038 +  chmod (newfile, S_IRUSR|S_IWUSR|S_IXUSR);
 28.1039 +  utime (newfile, &tbuf);
 28.1040 +
 28.1041 +}
 28.1042 +
 28.1043 +void maildir_expunge (MAILSTREAM *stream)
 28.1044 +{
 28.1045 +  MESSAGECACHE *elt;
 28.1046 +  unsigned long i = 1;
 28.1047 +  unsigned long n = 0;
 28.1048 +  unsigned long recent = stream->recent;
 28.1049 +  
 28.1050 +  maildir_gc (stream,GC_TEXTS);	/* invalidate texts */
 28.1051 +  mm_critical (stream);		/* go critical */
 28.1052 +  while (i <= stream->nmsgs) {	/* for each message */
 28.1053 +				/* if deleted, need to trash it */
 28.1054 +    if ((elt = mail_elt (stream,i))->deleted) {
 28.1055 +      snprintf (LOCAL->buf,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
 28.1056 +      if (unlink (LOCAL->buf)) {/* try to delete the message */
 28.1057 +	snprintf (LOCAL->buf,MAILTMPLEN,"Expunge of message %ld failed, aborted: %s",i,
 28.1058 +		 strerror (errno));
 28.1059 +	mm_log (LOCAL->buf,WARN);
 28.1060 +	break;
 28.1061 +      }
 28.1062 +				/* free the cached filename */
 28.1063 +      if (elt->maildirp) {
 28.1064 +	      fs_give ((void **) &elt->maildirp);
 28.1065 +	      elt->maildirp = 0; /* otherwise pine coredumps */
 28.1066 +		}
 28.1067 +      if (elt->recent) --recent;/* if recent, note one less recent message */
 28.1068 +      mail_expunged (stream,i);	/* notify upper levels */
 28.1069 +      n++;			/* count up one more expunged message */
 28.1070 +    }
 28.1071 +    else i++;			/* otherwise try next message */
 28.1072 +  }
 28.1073 +  if (n) {			/* output the news if any expunged */
 28.1074 +    snprintf (LOCAL->buf,MAILTMPLEN,"Expunged %ld messages",n);
 28.1075 +    mm_log (LOCAL->buf,(long) NIL);
 28.1076 +  }
 28.1077 +  else mm_log ("No messages deleted, so no update needed",(long) NIL);
 28.1078 +  mm_nocritical (stream);	/* release critical */
 28.1079 +				/* notify upper level of new mailbox size */
 28.1080 +  mail_exists (stream,stream->nmsgs);
 28.1081 +  mail_recent (stream,recent);
 28.1082 +}
 28.1083 +
 28.1084 +/* dont forget to process options in here */
 28.1085 +
 28.1086 +/* modified by sakira@sundent.mine.nu (03.01.13) */
 28.1087 +long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
 28.1088 +{
 28.1089 +  STRING st;
 28.1090 +  MESSAGECACHE *elt;
 28.1091 +  struct stat sbuf;
 28.1092 +  int fd;
 28.1093 +  unsigned long i;
 28.1094 +  char flags[MAILTMPLEN], date[MAILTMPLEN];
 28.1095 +
 28.1096 +				/* copy the messages */
 28.1097 +  if ((options & CP_UID) ? mail_uid_sequence (stream, sequence) : 
 28.1098 +  	mail_sequence (stream,sequence)) 
 28.1099 +  for (i = 1; i <= stream->nmsgs; i++)
 28.1100 +    if ((elt = mail_elt (stream,i))->sequence) {
 28.1101 +      sprintf (LOCAL->buf, "%s/%s", LOCAL->dir, (char *) elt->maildirp);
 28.1102 +      /*      snprintf (LOCAL->buf,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp); */
 28.1103 +      if ((fd = open (LOCAL->buf,O_RDONLY,NIL)) < 0) return NIL;
 28.1104 +      fstat (fd,&sbuf);		/* get size of message */
 28.1105 +
 28.1106 +      if (!elt->day) {
 28.1107 +	struct tm *tm = gmtime (&sbuf.st_mtime);
 28.1108 +	elt->day = tm->tm_mday; elt->month = tm->tm_mon + 1;
 28.1109 +	elt->year = tm->tm_year + 1900 - BASEYEAR;
 28.1110 +	elt->hours = tm->tm_hour; elt->minutes = tm->tm_min;
 28.1111 +	elt->seconds = tm->tm_sec;
 28.1112 +	elt->zhours = 0; elt->zminutes = 0;
 28.1113 +      }
 28.1114 +
 28.1115 +      if (sbuf.st_size > LOCAL->buflen) {
 28.1116 +	fs_give((void **) &LOCAL->buf);
 28.1117 +	LOCAL->buf = (char *) fs_get ((LOCAL->buflen = sbuf.st_size) + 1);
 28.1118 +      }
 28.1119 +
 28.1120 +				/* slurp message */
 28.1121 +      read(fd, LOCAL->buf, sbuf.st_size);
 28.1122 +      LOCAL->buf[sbuf.st_size] = '\0';
 28.1123 +      close(fd);
 28.1124 +      /* read (fd, s = (char *) fs_get (sbuf.st_size +1),sbuf.st_size); 
 28.1125 +      s[sbuf.st_size] = '\0';
 28.1126 +      close (fd); */
 28.1127 +
 28.1128 +      INIT (&st,mail_string,(void *) LOCAL->buf,sbuf.st_size);
 28.1129 +      flags[0] = flags[1] = '\0';
 28.1130 +      if (elt->seen) strcat(flags, " \\Seen");
 28.1131 +      if (elt->deleted) strcat(flags, " \\Deleted");
 28.1132 +      if (elt->answered) strcat(flags, " \\Answered");
 28.1133 +      if (elt->draft) strcat(flags, " \\Draft");
 28.1134 +      flags[0] = '(';
 28.1135 +      strcat(flags, ")");
 28.1136 +      mail_date(date, elt);
 28.1137 +      /* snprintf (LOCAL->buf,MAILTMPLEN,"%s%s%s%s%s)",
 28.1138 +	       elt->seen ? " \\Seen" : "",
 28.1139 +	       elt->deleted ? " \\Deleted" : "",
 28.1140 +	       elt->flagged ? " \\Flagged" : "",
 28.1141 +	       elt->answered ? " \\Answered" : "",
 28.1142 +	       (elt->seen || elt->deleted || elt->flagged || elt->answered) ?
 28.1143 +	       "" : " ");
 28.1144 +      LOCAL->buf[0] = '(';
 28.1145 +      mail_date (tmp,elt); */
 28.1146 +
 28.1147 +      if (!mail_append_full (NIL, mailbox, flags, date, &st)) return NIL;
 28.1148 +      if (options & CP_MOVE) elt->deleted = T;
 28.1149 +
 28.1150 +      /* if (!maildir_append (stream,mailbox,LOCAL->buf,tmp,&st)) {
 28.1151 +	fs_give ((void **) &s);	
 28.1152 +	return NIL; 
 28.1153 +	} */
 28.1154 +      /*      fs_give ((void **) &s); */	/* give back temporary space */
 28.1155 +    }
 28.1156 +  return T;			/* return success */
 28.1157 +}
 28.1158 +
 28.1159 +#if 0
 28.1160 +long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
 28.1161 +{
 28.1162 +  STRING st;
 28.1163 +  MESSAGECACHE *elt;
 28.1164 +  struct stat sbuf;
 28.1165 +  int fd;
 28.1166 +  long i;
 28.1167 +  char *s,tmp[MAILTMPLEN];
 28.1168 +				/* copy the messages */
 28.1169 +  if ((options & CP_UID) ? mail_uid_sequence (stream, sequence) : 
 28.1170 +  	mail_sequence (stream,sequence)) 
 28.1171 +  for (i = 1; i <= stream->nmsgs; i++)
 28.1172 +    if ((elt = mail_elt (stream,i))->sequence) {
 28.1173 +      snprintf (LOCAL->buf,MAILTMPLEN,"%s/%s",LOCAL->dir,(char *) elt->maildirp);
 28.1174 +      if ((fd = open (LOCAL->buf,O_RDONLY,NIL)) < 0) return NIL;
 28.1175 +      fstat (fd,&sbuf);		/* get size of message */
 28.1176 +				/* slurp message */
 28.1177 +      read (fd,s = (char *) fs_get (sbuf.st_size +1),sbuf.st_size);
 28.1178 +      s[sbuf.st_size] = '\0';	/* tie off file */
 28.1179 +      close (fd);		/* flush message file */
 28.1180 +      INIT (&st,mail_string,(void *) s,sbuf.st_size);
 28.1181 +      snprintf (LOCAL->buf,MAILTMPLEN,"%s%s%s%s%s)",
 28.1182 +	       elt->seen ? " \\Seen" : "",
 28.1183 +	       elt->deleted ? " \\Deleted" : "",
 28.1184 +	       elt->flagged ? " \\Flagged" : "",
 28.1185 +	       elt->answered ? " \\Answered" : "",
 28.1186 +	       (elt->seen || elt->deleted || elt->flagged || elt->answered) ?
 28.1187 +	       "" : " ");
 28.1188 +      LOCAL->buf[0] = '(';	/* open list */
 28.1189 +      mail_date (tmp,elt);	/* generate internal date */
 28.1190 +      if (!maildir_append (stream,mailbox,LOCAL->buf,tmp,&st)) {
 28.1191 +	fs_give ((void **) &s);	/* give back temporary space */
 28.1192 +	return NIL;
 28.1193 +      }
 28.1194 +      fs_give ((void **) &s);	/* give back temporary space */
 28.1195 +    }
 28.1196 +  return T;			/* return success */
 28.1197 +}
 28.1198 +#endif
 28.1199 +
 28.1200 +long maildir_append (MAILSTREAM *stream, char *mailbox, append_t af, void *data)
 28.1201 +{
 28.1202 +  int fd;
 28.1203 +  char c, *s;
 28.1204 +  char *flags, *date;
 28.1205 +  char tmp[MAILTMPLEN],file[MAILTMPLEN],path1[MAILTMPLEN],path2[MAILTMPLEN];
 28.1206 +  MESSAGECACHE elt;
 28.1207 +  STRING *message;
 28.1208 +  long i;
 28.1209 +  long size = 0;
 28.1210 +  long ret = LONGT;
 28.1211 +  short uf = 0;
 28.1212 +  
 28.1213 +  /*  
 28.1214 +     This is intentionaly made static.  Users can ask to save a LOT of messages
 28.1215 +     at once and this program can do that within one second. Dan's assumption
 28.1216 +     that time+pid+hostname always will be unique stops being true in this
 28.1217 +     case. So we will add yet another number to host part of message file's
 28.1218 +     name. Hostname is used only to make filename unique and Dan  explicitly
 28.1219 +     says that "<...>  Other than this [skipping filenames starting at dot] ,
 28.1220 +     readers should not attempt to parse filenames. <...>". Therefore this 
 28.1221 +     addition should be no problem. Am I right, Dan?   --AK
 28.1222 +  */ 
 28.1223 +  
 28.1224 +  static unsigned int transact = 0;
 28.1225 +
 28.1226 +  if (!stream) stream = &maildirproto;
 28.1227 +
 28.1228 +  if (flags) 			/* get flags if given */
 28.1229 +    uf = maildir_getflags (user_flags (&maildirproto),flags);
 28.1230 +
 28.1231 +				/* N.B.: can't use LOCAL->buf for tmp */
 28.1232 +				/* make sure valid mailbox */
 28.1233 +  if (!maildir_isvalid (mailbox, NIL)) {
 28.1234 +    snprintf (tmp,MAILTMPLEN,"Not a valid Maildir mailbox: %s",mailbox);
 28.1235 +    mm_log (tmp,ERROR);
 28.1236 +    return NIL;
 28.1237 +  }
 28.1238 +
 28.1239 +  if (!(*af)(stream, data, &flags, &date, &message)) return NIL;
 28.1240 +
 28.1241 +  mm_critical(stream);	/* go critical */
 28.1242 +  do {
 28.1243 +    if (!SIZE(message)) { /* guard againt zero-length */
 28.1244 +      mm_log("Append of zero-length message", ERROR);
 28.1245 +      ret = NIL;
 28.1246 +      break;
 28.1247 +    }
 28.1248 +
 28.1249 +    /* build file name we will use */
 28.1250 +    snprintf (file,MAILTMPLEN,"%u.%d.%09u.%s:3,%s%s%s%s",
 28.1251 +	      time (0),getpid (),transact++,mylocalhost (),
 28.1252 +	      uf&fFLAGGED ? "F" : "",uf&fANSWERED ? "R" : "",
 28.1253 +	      uf&fSEEN ? "S" : "",uf&fDELETED ? "T" : "");
 28.1254 +				/* build tmp file name */
 28.1255 +    snprintf (path1,MAILTMPLEN,"%s/../tmp/%s",maildir_file (tmp,mailbox),file);
 28.1256 +  
 28.1257 +    if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) {
 28.1258 +      snprintf (tmp,MAILTMPLEN,"Can't open append mailbox: %s",strerror (errno));
 28.1259 +      mm_log (tmp,ERROR);
 28.1260 +      return NIL;
 28.1261 +    }
 28.1262 +
 28.1263 +    i = SIZE (message);		/* get size of message */
 28.1264 +    s = (char *) fs_get (i + 1);	/* get space for the data */
 28.1265 +				/* copy the data w/o CR's */
 28.1266 +    while (i--) if ((c = SNX (message)) != '\015') s[size++] = c;
 28.1267 +				/* write the data */
 28.1268 +    if ((write (fd,s,size) < 0) || fsync (fd)) {
 28.1269 +      unlink (path1);		/* delete message */
 28.1270 +      snprintf (tmp,MAILTMPLEN,"Message append failed: %s",strerror (errno));
 28.1271 +      mm_log (tmp,ERROR);
 28.1272 +      ret = NIL;
 28.1273 +    }
 28.1274 +				/* build final filename to use */
 28.1275 +    snprintf (path2,MAILTMPLEN,"%s/../new/%s",maildir_file (tmp,mailbox),file);
 28.1276 +    if (link (path1,path2) < 0) {
 28.1277 +      snprintf (tmp,MAILTMPLEN,"Message append failed: %s",strerror (errno));
 28.1278 +      mm_log (tmp,ERROR);
 28.1279 +      ret = NIL;
 28.1280 +    }
 28.1281 +    unlink (path1);
 28.1282 +    fs_give ((void **) &s);	/* flush the buffer */
 28.1283 +    close (fd);			/* close the file */
 28.1284 +
 28.1285 +    if (ret) {
 28.1286 +      if (!(*af)(stream, data, &flags, &date, &message)) ret = NIL;
 28.1287 +    }
 28.1288 +  } while(ret && message);
 28.1289 +  
 28.1290 +  mm_nocritical (stream);	/* release critical */
 28.1291 +  return ret;
 28.1292 +}
 28.1293 +
 28.1294 +#if 0
 28.1295 +long maildir_append (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
 28.1296 +		   STRING *message)
 28.1297 +{
 28.1298 +  int fd;
 28.1299 +  char c,*s;
 28.1300 +  char tmp[MAILTMPLEN],file[MAILTMPLEN],path1[MAILTMPLEN],path2[MAILTMPLEN];
 28.1301 +  MESSAGECACHE elt;
 28.1302 +  long i;
 28.1303 +  long size = 0;
 28.1304 +  long ret = LONGT;
 28.1305 +  short uf = 0;
 28.1306 +  
 28.1307 +  /*  
 28.1308 +     This is intentionaly made static.  Users can ask to save a LOT of messages
 28.1309 +     at once and this program can do that within one second. Dan's assumption
 28.1310 +     that time+pid+hostname always will be unique stops being true in this
 28.1311 +     case. So we will add yet another number to host part of message file's
 28.1312 +     name. Hostname is used only to make filename unique and Dan  explicitly
 28.1313 +     says that "<...>  Other than this [skipping filenames starting at dot] ,
 28.1314 +     readers should not attempt to parse filenames. <...>". Therefore this 
 28.1315 +     addition should be no problem. Am I right, Dan?   --AK
 28.1316 +  */ 
 28.1317 +  
 28.1318 +  static unsigned int transact = 0;
 28.1319 +
 28.1320 +  if (flags) 			/* get flags if given */
 28.1321 +    uf = maildir_getflags (user_flags (&maildirproto),flags);
 28.1322 +
 28.1323 +/*  if (date) {			want to preserve date?
 28.1324 +    //syslog(LOG_INFO, "date: '%s'", date);
 28.1325 +				// yes, parse date into an elt
 28.1326 +    if (!mail_parse_date (&elt,date)) {
 28.1327 +      snprintf (tmp,MAILTMPLEN,"Bad date in append: %s",date);
 28.1328 +      mm_log (tmp,ERROR);
 28.1329 +      return NIL;
 28.1330 +    }
 28.1331 +  } */
 28.1332 +				/* N.B.: can't use LOCAL->buf for tmp */
 28.1333 +				/* make sure valid mailbox */
 28.1334 +  if (!maildir_isvalid (mailbox, NIL)) {
 28.1335 +    snprintf (tmp,MAILTMPLEN,"Not a valid Maildir mailbox: %s",mailbox);
 28.1336 +    mm_log (tmp,ERROR);
 28.1337 +    return NIL;
 28.1338 +  }
 28.1339 +				/* build file name we will use */
 28.1340 +  snprintf (file,MAILTMPLEN,"%u.%d.%09u.%s:3,%s%s%s%s",
 28.1341 +	   time (0),getpid (),transact++,mylocalhost (),
 28.1342 +	   uf&fFLAGGED ? "F" : "",uf&fANSWERED ? "R" : "",
 28.1343 +	   uf&fSEEN ? "S" : "",uf&fDELETED ? "T" : "");
 28.1344 +				/* build tmp file name */
 28.1345 +  snprintf (path1,MAILTMPLEN,"%s/../tmp/%s",maildir_file (tmp,mailbox),file);
 28.1346 +  
 28.1347 +  if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) {
 28.1348 +    snprintf (tmp,MAILTMPLEN,"Can't open append mailbox: %s",strerror (errno));
 28.1349 +    mm_log (tmp,ERROR);
 28.1350 +    return NIL;
 28.1351 +  }
 28.1352 +  i = SIZE (message);		/* get size of message */
 28.1353 +  s = (char *) fs_get (i + 1);	/* get space for the data */
 28.1354 +				/* copy the data w/o CR's */
 28.1355 +  while (i--) if ((c = SNX (message)) != '\015') s[size++] = c;
 28.1356 +  mm_critical (stream);		/* go critical */
 28.1357 +				/* write the data */
 28.1358 +  if ((write (fd,s,size) < 0) || fsync (fd)) {
 28.1359 +    unlink (path1);		/* delete message */
 28.1360 +    snprintf (tmp,MAILTMPLEN,"Message append failed: %s",strerror (errno));
 28.1361 +    mm_log (tmp,ERROR);
 28.1362 +    ret = NIL;
 28.1363 +  }
 28.1364 +				/* build final filename to use */
 28.1365 +  snprintf (path2,MAILTMPLEN,"%s/../new/%s",maildir_file (tmp,mailbox),file);
 28.1366 +  if (link (path1,path2) < 0) {
 28.1367 +    snprintf (tmp,MAILTMPLEN,"Message append failed: %s",strerror (errno));
 28.1368 +    mm_log (tmp,ERROR);
 28.1369 +    ret = NIL;
 28.1370 +  }
 28.1371 +  unlink (path1);
 28.1372 +  
 28.1373 +  close (fd);			/* close the file */
 28.1374 +  mm_nocritical (stream);	/* release critical */
 28.1375 +  fs_give ((void **) &s);	/* flush the buffer */
 28.1376 +  return ret;
 28.1377 +}
 28.1378 +#endif
 28.1379 +
 28.1380 +short bezerk_getflags (MAILSTREAM *stream,char *flag)
 28.1381 +{
 28.1382 +  char *t,tmp[MAILTMPLEN],err[MAILTMPLEN];
 28.1383 +  short f = 0;
 28.1384 +  short i,j;
 28.1385 +  if (flag && *flag) {		/* no-op if no flag string */
 28.1386 +				/* check if a list and make sure valid */
 28.1387 +    if ((i = (*flag == '(')) ^ (flag[strlen (flag)-1] == ')')) {
 28.1388 +      mm_log ("Bad flag list",ERROR);
 28.1389 +      return NIL;
 28.1390 +    }
 28.1391 +				/* copy the flag string w/o list construct */
 28.1392 +    strncpy (tmp,flag+i,(j = strlen (flag) - (2*i)));
 28.1393 +    tmp[j] = '\0';
 28.1394 +    t = ucase (tmp);		/* uppercase only from now on */
 28.1395 +
 28.1396 +    while (t && *t) {		/* parse the flags */
 28.1397 +      if (*t == '\\') {		/* system flag? */
 28.1398 +	switch (*++t) {		/* dispatch based on first character */
 28.1399 +	case 'S':		/* possible \Seen flag */
 28.1400 +	  if (t[1] == 'E' && t[2] == 'E' && t[3] == 'N') i = fSEEN;
 28.1401 +	  t += 4;		/* skip past flag name */
 28.1402 +	  break;
 28.1403 +	case 'D':		/* possible \Deleted flag */
 28.1404 +	  if (t[1] == 'E' && t[2] == 'L' && t[3] == 'E' && t[4] == 'T' &&
 28.1405 +	      t[5] == 'E' && t[6] == 'D') i = fDELETED;
 28.1406 +	  t += 7;		/* skip past flag name */
 28.1407 +	  break;
 28.1408 +	case 'F':		/* possible \Flagged flag */
 28.1409 +	  if (t[1] == 'L' && t[2] == 'A' && t[3] == 'G' && t[4] == 'G' &&
 28.1410 +	      t[5] == 'E' && t[6] == 'D') i = fFLAGGED;
 28.1411 +	  t += 7;		/* skip past flag name */
 28.1412 +	  break;
 28.1413 +	case 'A':		/* possible \Answered flag */
 28.1414 +	  if (t[1] == 'N' && t[2] == 'S' && t[3] == 'W' && t[4] == 'E' &&
 28.1415 +	      t[5] == 'R' && t[6] == 'E' && t[7] == 'D') i = fANSWERED;
 28.1416 +	  t += 8;		/* skip past flag name */
 28.1417 +	  break;
 28.1418 +	default:		/* unknown */
 28.1419 +	  i = 0;
 28.1420 +	  break;
 28.1421 +	}
 28.1422 +				/* add flag to flags list */
 28.1423 +	if (i && ((*t == '\0') || (*t++ == ' '))) f |= i;
 28.1424 +      }
 28.1425 +      else {			/* no user flags yet */
 28.1426 +	return f;
 28.1427 +	t = strtok (t," ");	/* isolate flag name */
 28.1428 +	/*	snprintf (err,MAILTMPLEN,"Unknown flag: %.80s",t); */
 28.1429 +	t = strtok (NIL," ");	/* get next flag */
 28.1430 +	/*	mm_log (err,ERROR); */
 28.1431 +      }
 28.1432 +    }
 28.1433 +  }
 28.1434 +  return f;
 28.1435 +}
 28.1436 +
 28.1437 +short maildir_getflags (MAILSTREAM *stream,char *flag)
 28.1438 +{
 28.1439 +  return bezerk_getflags (stream,flag); /* nothing exciting, reuse old code */
 28.1440 +}
 28.1441 +
 28.1442 +long maildir_delete (MAILSTREAM *stream,char *mailbox)
 28.1443 +{
 28.1444 +  DIR *dirp;
 28.1445 +  struct direct *d;
 28.1446 +  int i,j;
 28.1447 +  char tmp[MAILTMPLEN],err[MAILTMPLEN];
 28.1448 +  char *subdir_names[] = {"cur/","new/","tmp/",NULL};
 28.1449 +
 28.1450 +				/* check if mailbox even exists */
 28.1451 +  if (!maildir_isvalid (mailbox,NIL)) {
 28.1452 +/*    sprintf (tmp,"Can't delete mailbox %s: no such mailbox",mailbox);
 28.1453 +    mm_log (tmp,ERROR);
 28.1454 +    return NIL; */
 28.1455 +    /*syslog(LOG_INFO, "Invalid maildir in delete()"); */
 28.1456 +    return T; /* well.. a stupid hack to get by a problem in netscape ..
 28.1457 +    		it remembers folders locally, and if a folder is deleted on
 28.1458 +    		another machine, you have no way removing it on any other
 28.1459 +    		netscapes... */
 28.1460 +  }
 28.1461 +
 28.1462 +				/* get name of directory */
 28.1463 +  i = strlen (maildir_file (tmp,mailbox)) + 1;
 28.1464 +  for (j = 0; subdir_names[j]; j++) {
 28.1465 +    strncpy (tmp + i - 4,subdir_names[j], MAILTMPLEN);
 28.1466 +    if (dirp = opendir (tmp)) {	/* open directory */
 28.1467 +      while (d = readdir (dirp))	/* empty the directory */
 28.1468 +	if (strcmp (d->d_name,".") && strcmp (d->d_name,"..")) {
 28.1469 +	  strncpy (tmp + i,d->d_name, MAILTMPLEN);
 28.1470 +	  /*syslog(LOG_INFO, "unlink1: '%s'");*/
 28.1471 +	  unlink (tmp);
 28.1472 +	}
 28.1473 +      closedir (dirp);		/* flush directory */
 28.1474 +    }
 28.1475 +				/* remove the subdir */
 28.1476 +    tmp[i + 3] = '\0';
 28.1477 +    /*syslog(LOG_INFO, "tmp: '%s'", tmp);*/
 28.1478 +    if (rmdir (tmp)) {
 28.1479 +    /*  sprintf (err,"Can't delete directory %s: %s",tmp,strerror (errno));
 28.1480 +      mm_log (err,ERROR);*/
 28.1481 +    }
 28.1482 +  }
 28.1483 +
 28.1484 +				/* try to remove the directory */
 28.1485 +  *(tmp + i - 5) = '\0';
 28.1486 +  /*syslog(LOG_INFO, "tmp2: '%s'", tmp);*/
 28.1487 +  if (rmdir (tmp)) {
 28.1488 +/*    sprintf (err,"Can't delete mailbox %s: %s",mailbox,strerror (errno));
 28.1489 +    mm_log (err,ERROR);
 28.1490 +    return NIL; */
 28.1491 +  }
 28.1492 +  return T;			/* return success */
 28.1493 +}
 28.1494 +
 28.1495 +long maildir_rename (MAILSTREAM *stream,char *old,char *new)
 28.1496 +{
 28.1497 +  char tmp[MAILTMPLEN],tmpnew[MAILTMPLEN];
 28.1498 +
 28.1499 +				/* old mailbox name must be valid */
 28.1500 +  if (!maildir_isvalid (old,NIL)) {
 28.1501 +    snprintf (tmp,MAILTMPLEN,"Can't rename mailbox %s: no such mailbox",old);
 28.1502 +    mm_log (tmp,ERROR);
 28.1503 +    return NIL;
 28.1504 +  }
 28.1505 +
 28.1506 +				/* new mailbox name must not exist */
 28.1507 +  if (access (maildir_file (tmp,new),F_OK) == 0) {
 28.1508 +    snprintf (tmp,MAILTMPLEN,"Can't rename to mailbox %s: destination already exists",new);
 28.1509 +    mm_log (tmp,ERROR);
 28.1510 +    return NIL;
 28.1511 +  }
 28.1512 +
 28.1513 +				/* try to rename the directory */
 28.1514 +  if (rename (maildir_file (tmp,old),maildir_file (tmpnew,new))) {
 28.1515 +    snprintf (tmp,MAILTMPLEN,"Can't rename mailbox %s to %s: %s",old,new,strerror (errno));
 28.1516 +    mm_log (tmp,ERROR);
 28.1517 +    return NIL;
 28.1518 +  }
 28.1519 +  return T;			/* return success */
 28.1520 +}
 28.1521 +
 28.1522 +long maildir_sub (MAILSTREAM *stream,char *mailbox)
 28.1523 +{
 28.1524 +  char tmp[MAILTMPLEN];
 28.1525 +  return sm_subscribe (mailbox);
 28.1526 +}
 28.1527 +
 28.1528 +long maildir_unsub (MAILSTREAM *stream,char *mailbox)
 28.1529 +{
 28.1530 +  char tmp[MAILTMPLEN];
 28.1531 +  return sm_unsubscribe (mailbox);
 28.1532 +}
 28.1533 +
 28.1534 +void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat)
 28.1535 +{
 28.1536 + void *sdb = NIL;
 28.1537 +  char *s;
 28.1538 +                                /* get canonical form of name */
 28.1539 +  if ((s = sm_read (&sdb))) {
 28.1540 +    do if (pmatch_full (s,pat,'/')) mm_lsub (stream,'/',s,NIL);
 28.1541 +    while (s = sm_read (&sdb)); /* until no more subscriptions */
 28.1542 +  }
 28.1543 +
 28.1544 +}
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/src/osdep/unix/maildir.h	Mon Sep 14 19:23:11 2009 +0900
    29.3 @@ -0,0 +1,58 @@
    29.4 +/*
    29.5 + * Please read maildir.c for license and information
    29.6 + *
    29.7 + */
    29.8 +
    29.9 +#define MAILDIRPATH "Maildir"
   29.10 +	
   29.11 +typedef struct maildir_local {
   29.12 +  unsigned int inbox : 1;	/* if it is an INBOX or not */
   29.13 +  unsigned int dirty : 1;	/* diskcopy needs updating */
   29.14 +  char *dir;			/* mail directory name */
   29.15 +  char *buf;			/* temporary buffer */
   29.16 +  char *hdr;			/* current header */
   29.17 +  unsigned long buflen;		/* current size of temporary buffer */
   29.18 +  time_t scantime;		/* last time directory scanned */
   29.19 +} MAILDIRLOCAL;
   29.20 +
   29.21 +/* Convenient access to local data */
   29.22 +
   29.23 +#define LOCAL ((MAILDIRLOCAL *) stream->local)
   29.24 +
   29.25 +/* Function prototypes */
   29.26 +
   29.27 +DRIVER *maildir_valid (char *name);
   29.28 +int maildir_isvalid (char *name,long justname);
   29.29 +MAILSTREAM *maildir_open (MAILSTREAM *stream);
   29.30 +void maildir_gc (MAILSTREAM *stream,long gcflags);
   29.31 +void maildir_close (MAILSTREAM *stream, long options);
   29.32 +long maildir_ping (MAILSTREAM *stream);
   29.33 +long maildir_ping_core (MAILSTREAM *stream);
   29.34 +void maildir_check (MAILSTREAM *stream);
   29.35 +long maildir_fetchtext (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);
   29.36 +char *maildir_fetchheader (MAILSTREAM *stream,unsigned long msgno,
   29.37 +		unsigned long *length, long flags);
   29.38 +void maildir_fast (MAILSTREAM *stream,char *sequence,long flags);
   29.39 +void maildir_list (MAILSTREAM *stream,char *ref,char *pat);
   29.40 +void *maildir_parameters (long function,void *value);
   29.41 +long maildir_create (MAILSTREAM *stream,char *mailbox);
   29.42 +void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt);
   29.43 +void maildir_expunge (MAILSTREAM *stream);
   29.44 +long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);
   29.45 +long maildir_append (MAILSTREAM *stream, char *mailbox, append_t af, void *data);
   29.46 +/* long maildir_append (MAILSTREAM *stream,char *mailbox,char *flags,char *date,
   29.47 +   STRING *message); */
   29.48 +short maildir_getflags (MAILSTREAM *stream,char *flag);
   29.49 +long maildir_delete (MAILSTREAM *stream,char *mailbox);
   29.50 +long maildir_rename (MAILSTREAM *stream,char *old,char *new);
   29.51 +long maildir_sub (MAILSTREAM *stream,char *mailbox);
   29.52 +long maildir_unsub (MAILSTREAM *stream,char *mailbox);
   29.53 +void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat);
   29.54 +
   29.55 +/* utility functions */
   29.56 +char *maildir_file (char *dst,char *name);
   29.57 +void maildir_copynew (const char *mailbox);
   29.58 +int maildir_select (struct direct *name);
   29.59 +/* int maildir_namesort (struct direct **d1,struct direct **d2); */
   29.60 +int maildir_namesort (const void *, const void *);
   29.61 +void maildir_listwork(char *name, MAILSTREAM *stream, char *s2, char *subdir, int flag);
    30.1 --- a/src/osdep/unix/tcp_unix.c	Mon Sep 14 15:17:45 2009 +0900
    30.2 +++ b/src/osdep/unix/tcp_unix.c	Mon Sep 14 19:23:11 2009 +0900
    30.3 @@ -818,6 +818,20 @@
    30.4    return stream->localhost;	/* return local host name */
    30.5  }
    30.6  
    30.7 +/* Get $TCPREMOTEHOST || $TCPREMOTEHOST
    30.8 + * If invoked via tcpserver or couriertcpd, consult $TCPREMOTEHOST
    30.9 + * or $TCPREMOTEIP
   30.10 + */
   30.11 +char* gettcpremoteip()
   30.12 +{
   30.13 +  if (getenv("TCPREMOTEHOST") && strcmp("0", getenv("TCPREMOTEHOST"))) {
   30.14 +    return getenv("TCPREMOTEHOST");
   30.15 +  } else if (getenv("TCPREMOTEIP")) {
   30.16 +    return getenv("TCPREMOTEIP");
   30.17 +  }
   30.18 +  return "NON-IPv4";
   30.19 +}
   30.20 +
   30.21  /* TCP/IP get client host address (server calls only)
   30.22   * Returns: client host address
   30.23   */
   30.24 @@ -848,6 +862,15 @@
   30.25    if (!myClientHost) {
   30.26      size_t sadrlen;
   30.27      struct sockaddr *sadr = ip_newsockaddr (&sadrlen);
   30.28 +#ifdef INET6
   30.29 +    if (getenv("TCPREMOTEIP")) {
   30.30 +      myClientHost =
   30.31 +         cpystr((getenv("TCPREMOTEHOST")
   30.32 + 		&& strcasecmp("UNKNOWN", getenv("TCPREMOTEHOST")))
   30.33 + 		? getenv("TCPREMOTEHOST")
   30.34 + 		: getenv("TCPREMOTEIP"));
   30.35 +    } else
   30.36 +#endif
   30.37      if (getpeername (0,sadr,(void *) &sadrlen)) {
   30.38        char *s,*t,*v,tmp[MAILTMPLEN];
   30.39        if ((s = getenv (t = "SSH_CLIENT")) ||
   30.40 @@ -911,7 +934,8 @@
   30.41      size_t sadrlen;
   30.42      struct sockaddr *sadr = ip_newsockaddr (&sadrlen);
   30.43  				/* get stdin's name */
   30.44 -    if (getsockname (0,sadr,(void *) &sadrlen))
   30.45 +    if (getsockname (0,sadr,(void *) &sadrlen) ||
   30.46 +        (myServerPort = ip_sockaddrtoport (sadr)) < 0)
   30.47        myServerHost = cpystr (mylocalhost ());
   30.48      else {			/* get stdin's name */
   30.49        myServerHost = tcp_name (sadr,NIL);
    31.1 --- a/src/osdep/unix/unix.c	Mon Sep 14 15:17:45 2009 +0900
    31.2 +++ b/src/osdep/unix/unix.c	Mon Sep 14 19:23:11 2009 +0900
    31.3 @@ -202,6 +202,7 @@
    31.4  
    31.5  				/* driver parameters */
    31.6  static long unix_fromwidget = T;
    31.7 +char *myMailSuffix =NIL;	/* home directory name */
    31.8  
    31.9  /* UNIX mail validate mailbox
   31.10   * Accepts: mailbox name
   31.11 @@ -2401,6 +2402,15 @@
   31.12    }
   31.13    f->filepos += size;		/* update file position */
   31.14  }
   31.15 +
   31.16 +/* Return my mail suffix(of qmail or Postfix)
   31.17 + * Returns: my mail address extensional suffix
   31.18 + */
   31.19 +
   31.20 +char *mymailsuffix ()
   31.21 +{
   31.22 +  return myMailSuffix ? myMailSuffix : "";
   31.23 +}
   31.24  
   31.25  /* MBOX mail routines */
   31.26  

UW-IMAP'd extensions by yuuji