summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2013-02-04 02:48:34 +0100
committermanuel <manuel@mausz.at>2013-02-04 02:48:34 +0100
commit5d47a7101a2394c7f7bb288585464fa293a2ad33 (patch)
tree0c371687c8791b2278c5b8049bbd64a7de1d0863
parent86d5a6ec30ceea44e9459394d2e6403642cdd158 (diff)
downloadqmail-5d47a7101a2394c7f7bb288585464fa293a2ad33.tar.gz
qmail-5d47a7101a2394c7f7bb288585464fa293a2ad33.tar.bz2
qmail-5d47a7101a2394c7f7bb288585464fa293a2ad33.zip
[PATCH] maildir++ for qmail-local and qmail-pop3d
Patch to make qmail-local and qmail-pop3d compatible with the maildir++ quota system that is used by vpopmail and courier-imap qmail-maildir++
-rw-r--r--Makefile45
-rw-r--r--TARGETS8
-rw-r--r--maildirflags.c23
-rw-r--r--maildirgetquota.c50
-rw-r--r--maildirgetquota.h30
-rw-r--r--maildirmisc.h145
-rw-r--r--maildiropen.c133
-rw-r--r--maildirparsequota.c44
-rw-r--r--maildirquota.c685
-rw-r--r--maildirquota.h45
-rw-r--r--numlib.h45
-rw-r--r--overmaildirquota.c43
-rw-r--r--qmail-local.c13
-rw-r--r--qmail-pop3d.c75
-rw-r--r--strpidt.c26
-rw-r--r--strtimet.c26
16 files changed, 1413 insertions, 23 deletions
diff --git a/Makefile b/Makefile
index 1000b58..5f676dd 100644
--- a/Makefile
+++ b/Makefile
@@ -894,6 +894,38 @@ datetime.h gen_alloc.h stralloc.h gen_alloc.h str.h exit.h hfield.h \
894readwrite.h open.h headerbody.h maildir.h strerr.h 894readwrite.h open.h headerbody.h maildir.h strerr.h
895 ./compile maildirwatch.c 895 ./compile maildirwatch.c
896 896
897maildirgetquota.o: \
898compile maildirgetquota.c maildirgetquota.h maildirmisc.h
899 ./compile maildirgetquota.c
900
901maildirflags.o: \
902compile maildirflags.c
903 ./compile maildirflags.c
904
905maildiropen.o: \
906compile maildiropen.c maildirmisc.h
907 ./compile maildiropen.c
908
909maildirparsequota.o: \
910compile maildirparsequota.c
911 ./compile maildirparsequota.c
912
913maildirquota.o: \
914compile maildirquota.c maildirquota.h maildirmisc.h numlib.h
915 ./compile maildirquota.c
916
917overmaildirquota.o: \
918compile overmaildirquota.c
919 ./compile overmaildirquota.c
920
921strtimet.o: \
922compile strtimet.c
923 ./compile strtimet.c
924
925strpidt.o: \
926compile strpidt.c
927 ./compile strpidt.c
928
897mailsubj: \ 929mailsubj: \
898warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split 930warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split
899 cat warn-auto.sh mailsubj.sh \ 931 cat warn-auto.sh mailsubj.sh \
@@ -1178,12 +1210,15 @@ qmail-local: \
1178load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \ 1210load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \
1179slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \ 1211slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \
1180wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \ 1212wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
1181fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib 1213fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib maildirquota.o \
1214maildirgetquota.o maildiropen.o maildirparsequota.o overmaildirquota.o \
1215strtimet.o strpidt.o
1182 ./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \ 1216 ./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \
1183 slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \ 1217 slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \
1184 lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \ 1218 lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \
1185 substdio.a error.a str.a fs.a datetime.a auto_qmail.o \ 1219 substdio.a error.a str.a fs.a datetime.a auto_qmail.o \
1186 auto_patrn.o `cat socket.lib` 1220 auto_patrn.o `cat socket.lib` maildirquota.o maildirgetquota.o \
1221 maildiropen.o maildirparsequota.o overmaildirquota.o strtimet.o strpidt.o
1187 1222
1188qmail-local.0: \ 1223qmail-local.0: \
1189qmail-local.8 1224qmail-local.8
@@ -1273,11 +1308,13 @@ readwrite.h open.h error.h case.h auto_qmail.h
1273qmail-pop3d: \ 1308qmail-pop3d: \
1274load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \ 1309load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \
1275maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \ 1310maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \
1276stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib 1311stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib maildirquota.o \
1312maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o
1277 ./load qmail-pop3d commands.o case.a timeoutread.o \ 1313 ./load qmail-pop3d commands.o case.a timeoutread.o \
1278 timeoutwrite.o maildir.o prioq.o now.o env.a strerr.a sig.a \ 1314 timeoutwrite.o maildir.o prioq.o now.o env.a strerr.a sig.a \
1279 open.a getln.a stralloc.a alloc.a substdio.a error.a str.a \ 1315 open.a getln.a stralloc.a alloc.a substdio.a error.a str.a \
1280 fs.a `cat socket.lib` 1316 fs.a `cat socket.lib` maildirquota.o maildirgetquota.o \
1317 maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o
1281 1318
1282qmail-pop3d.0: \ 1319qmail-pop3d.0: \
1283qmail-pop3d.8 1320qmail-pop3d.8
diff --git a/TARGETS b/TARGETS
index 63c8d4c..949bc46 100644
--- a/TARGETS
+++ b/TARGETS
@@ -16,6 +16,14 @@ myctime.o
16slurpclose.o 16slurpclose.o
17make-makelib 17make-makelib
18makelib 18makelib
19maildirflags.o
20maildirparsequota.o
21maildiropen.o
22maildirgetquota.o
23maildirquota.o
24overmaildirquota.o
25strtimet.o
26strpidt.o
19case_diffb.o 27case_diffb.o
20case_diffs.o 28case_diffs.o
21case_lowerb.o 29case_lowerb.o
diff --git a/maildirflags.c b/maildirflags.c
new file mode 100644
index 0000000..8ac460c
--- /dev/null
+++ b/maildirflags.c
@@ -0,0 +1,23 @@
1/*
2** Copyright 2000 Double Precision, Inc.
3** See COPYING for distribution information.
4*/
5
6#include <sys/types.h>
7#include <string.h>
8
9static const char rcsid[]="$Id: maildirflags.c,v 1.1 2000/10/07 01:10:19 mrsam Exp $";
10
11int maildir_hasflag(const char *filename, char flag)
12{
13 const char *p=strrchr(filename, '/');
14
15 if (p)
16 filename=p+1;
17
18 p=strrchr(p, ':');
19 if (p && strncmp(p, ":2,", 3) == 0 &&
20 strchr(p+3, flag))
21 return (1);
22 return (0);
23}
diff --git a/maildirgetquota.c b/maildirgetquota.c
new file mode 100644
index 0000000..1c541f8
--- /dev/null
+++ b/maildirgetquota.c
@@ -0,0 +1,50 @@
1/*
2** Copyright 1998 - 2000 Double Precision, Inc.
3** See COPYING for distribution information.
4*/
5
6#include "maildirgetquota.h"
7#include "maildirmisc.h"
8#if HAVE_UNISTD_H
9#include <unistd.h>
10#endif
11#include <stdlib.h>
12#include <string.h>
13#include <fcntl.h>
14#include <sys/types.h>
15#include <sys/stat.h>
16
17int maildir_getquota(const char *dir, char buf[QUOTABUFSIZE])
18{
19char *p;
20struct stat stat_buf;
21int n;
22int l;
23
24 p=(char *)malloc(strlen(dir)+sizeof("/maildirfolder"));
25 if (!p) return (-1);
26
27 strcat(strcpy(p, dir), "/maildirfolder");
28 if (stat(p, &stat_buf) == 0)
29 {
30 strcat(strcpy(p, dir), "/..");
31 n=maildir_getquota(p, buf);
32 free(p);
33 return (n);
34 }
35
36 strcat(strcpy(p, dir), "/maildirsize");
37 n=maildir_safeopen(p, O_RDONLY, 0);
38 free(p);
39 if (n < 0) return (n);
40 if ((l=read(n, buf, QUOTABUFSIZE-1)) < 0)
41 {
42 close(n);
43 return (-1);
44 }
45 close(n);
46 for (n=0; n<l; n++)
47 if (buf[n] == '\n') break;
48 buf[n]=0;
49 return (0);
50}
diff --git a/maildirgetquota.h b/maildirgetquota.h
new file mode 100644
index 0000000..6fc4cc4
--- /dev/null
+++ b/maildirgetquota.h
@@ -0,0 +1,30 @@
1#ifndef maildirgetquota_h
2#define maildirgetquota_h
3
4/*
5** Copyright 1998 - 1999 Double Precision, Inc.
6** See COPYING for distribution information.
7*/
8
9#if HAVE_CONFIG_H
10#include "config.h"
11#endif
12
13#include <sys/types.h>
14#include <stdio.h>
15
16#ifdef __cplusplus
17extern "C" {
18#endif
19
20static const char maildirgetquota_h_rcsid[]="$Id: maildirgetquota.h,v 1.5 1999/12/06 13:21:05 mrsam Exp $";
21
22#define QUOTABUFSIZE 256
23
24int maildir_getquota(const char *, char [QUOTABUFSIZE]);
25
26#ifdef __cplusplus
27}
28#endif
29
30#endif
diff --git a/maildirmisc.h b/maildirmisc.h
new file mode 100644
index 0000000..86743bc
--- /dev/null
+++ b/maildirmisc.h
@@ -0,0 +1,145 @@
1#ifndef maildirmisc_h
2#define maildirmisc_h
3
4/*
5** Copyright 2000 Double Precision, Inc.
6** See COPYING for distribution information.
7*/
8
9#if HAVE_CONFIG_H
10#include "config.h"
11#endif
12
13#ifdef __cplusplus
14extern "C" {
15#endif
16
17static const char maildirmisc_h_rcsid[]="$Id: maildirmisc.h,v 1.8 2000/12/25 17:33:06 mrsam Exp $";
18
19/*
20**
21** Miscellaneous maildir-related code
22**
23*/
24
25/* Some special folders */
26
27#define INBOX "INBOX"
28#define DRAFTS "Drafts"
29#define SENT "Sent"
30#define TRASH "Trash"
31
32#define SHAREDSUBDIR "shared-folders"
33
34char *maildir_folderdir(const char *, /* maildir */
35 const char *); /* folder name */
36 /* Returns the directory corresponding to foldername (foldername is
37 ** checked to make sure that it's a valid name, else we set errno
38 ** to EINVAL, and return (0).
39 */
40
41char *maildir_filename(const char *, /* maildir */
42 const char *, /* folder */
43 const char *); /* filename */
44 /*
45 ** Builds the filename to this message, suitable for opening.
46 ** If the file doesn't appear to be there, search the maildir to
47 ** see if someone changed the flags, and return the current filename.
48 */
49
50int maildir_safeopen(const char *, /* filename */
51 int, /* mode */
52 int); /* perm */
53
54/*
55** Same arguments as open(). When we're accessing a shared maildir,
56** prevent someone from playing cute and dumping a bunch of symlinks
57** in there. This function will open the indicate file only if the
58** last component is not a symlink.
59** This is implemented by opening the file with O_NONBLOCK (to prevent
60** a DOS attack of someone pointing the symlink to a pipe, causing
61** the open to hang), clearing O_NONBLOCK, then stat-int the file
62** descriptor, lstating the filename, and making sure that dev/ino
63** match.
64*/
65
66int maildir_semisafeopen(const char *, /* filename */
67 int, /* mode */
68 int); /* perm */
69
70/*
71** Same thing, except that we allow ONE level of soft link indirection,
72** because we're reading from our own maildir, which points to the
73** message in the sharable maildir.
74*/
75
76int maildir_mkdir(const char *); /* directory */
77/*
78** Create maildir including all subdirectories in the path (like mkdir -p)
79*/
80
81void maildir_purgetmp(const char *); /* maildir */
82 /* purges old stuff out of tmp */
83
84void maildir_purge(const char *, /* directory */
85 unsigned); /* time_t to purge */
86
87void maildir_getnew(const char *, /* maildir */
88 const char *); /* folder */
89 /* move messages from new to cur */
90
91int maildir_deletefolder(const char *, /* maildir */
92 const char *); /* folder */
93 /* deletes a folder */
94
95int maildir_mddelete(const char *); /* delete a maildir folder by path */
96
97void maildir_list_sharable(const char *, /* maildir */
98 void (*)(const char *, void *), /* callback function */
99 void *); /* 2nd arg to callback func */
100 /* list sharable folders */
101
102int maildir_shared_subscribe(const char *, /* maildir */
103 const char *); /* folder */
104 /* subscribe to a shared folder */
105
106void maildir_list_shared(const char *, /* maildir */
107 void (*)(const char *, void *), /* callback function */
108 void *); /* 2nd arg to the callback func */
109 /* list subscribed folders */
110
111int maildir_shared_unsubscribe(const char *, /* maildir */
112 const char *); /* folder */
113 /* unsubscribe from a shared folder */
114
115char *maildir_shareddir(const char *, /* maildir */
116 const char *); /* folder */
117 /*
118 ** Validate and return a path to a shared folder. folderdir must be
119 ** a name of a valid shared folder.
120 */
121
122void maildir_shared_sync(const char *); /* maildir */
123 /* "sync" the shared folder */
124
125int maildir_sharedisro(const char *); /* maildir */
126 /* maildir is a shared read-only folder */
127
128int maildir_unlinksharedmsg(const char *); /* filename */
129 /* Remove a message from a shared folder */
130
131/* Internal function that reads a symlink */
132
133char *maildir_getlink(const char *);
134
135 /* Determine whether the maildir filename has a certain flag */
136
137int maildir_hasflag(const char *filename, char);
138
139#define MAILDIR_DELETED(f) maildir_hasflag((f), 'T')
140
141#ifdef __cplusplus
142}
143#endif
144
145#endif
diff --git a/maildiropen.c b/maildiropen.c
new file mode 100644
index 0000000..bcaadd4
--- /dev/null
+++ b/maildiropen.c
@@ -0,0 +1,133 @@
1/*
2** Copyright 2000 Double Precision, Inc.
3** See COPYING for distribution information.
4*/
5
6#if HAVE_CONFIG_H
7#include "config.h"
8#endif
9
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <string.h>
13#include <stdlib.h>
14#include <time.h>
15#if HAVE_UNISTD_H
16#include <unistd.h>
17#endif
18#include <stdio.h>
19#include <ctype.h>
20#include <errno.h>
21#include <fcntl.h>
22
23#include "maildirmisc.h"
24
25static const char rcsid[]="$Id: maildiropen.c,v 1.7 2000/12/10 04:43:44 mrsam Exp $";
26
27char *maildir_getlink(const char *filename)
28{
29#if HAVE_READLINK
30size_t bufsiz;
31char *buf;
32
33 bufsiz=0;
34 buf=0;
35
36 for (;;)
37 {
38 int n;
39
40 if (buf) free(buf);
41 bufsiz += 256;
42 if ((buf=malloc(bufsiz)) == 0)
43 {
44 perror("malloc");
45 return (0);
46 }
47 if ((n=readlink(filename, buf, bufsiz)) < 0)
48 {
49 free(buf);
50 return (0);
51 }
52 if (n < bufsiz)
53 {
54 buf[n]=0;
55 break;
56 }
57 }
58 return (buf);
59#else
60 return (0);
61#endif
62}
63
64int maildir_semisafeopen(const char *path, int mode, int perm)
65{
66
67#if HAVE_READLINK
68
69char *l=maildir_getlink(path);
70
71 if (l)
72 {
73 int f;
74
75 if (*l != '/')
76 {
77 char *q=malloc(strlen(path)+strlen(l)+2);
78 char *s;
79
80 if (!q)
81 {
82 free(l);
83 return (-1);
84 }
85
86 strcpy(q, path);
87 if ((s=strchr(q, '/')) != 0)
88 s[1]=0;
89 else *q=0;
90 strcat(q, l);
91 free(l);
92 l=q;
93 }
94
95 f=maildir_safeopen(l, mode, perm);
96
97 free(l);
98 return (f);
99 }
100#endif
101
102 return (maildir_safeopen(path, mode, perm));
103}
104
105int maildir_safeopen(const char *path, int mode, int perm)
106{
107struct stat stat1, stat2;
108
109int fd=open(path, mode
110#ifdef O_NONBLOCK
111 | O_NONBLOCK
112#else
113 | O_NDELAY
114#endif
115 , perm);
116
117 if (fd < 0) return (fd);
118 if (fcntl(fd, F_SETFL, (mode & O_APPEND)) || fstat(fd, &stat1)
119 || lstat(path, &stat2))
120 {
121 close(fd);
122 return (-1);
123 }
124
125 if (stat1.st_dev != stat2.st_dev || stat1.st_ino != stat2.st_ino)
126 {
127 close(fd);
128 errno=ENOENT;
129 return (-1);
130 }
131
132 return (fd);
133}
diff --git a/maildirparsequota.c b/maildirparsequota.c
new file mode 100644
index 0000000..35e7d99
--- /dev/null
+++ b/maildirparsequota.c
@@ -0,0 +1,44 @@
1/*
2** Copyright 1998 - 1999 Double Precision, Inc.
3** See COPYING for distribution information.
4*/
5
6#if HAVE_CONFIG_H
7#include "config.h"
8#endif
9#include "maildirquota.h"
10#include <stdlib.h>
11#include <string.h>
12
13static const char rcsid[]="$Id: maildirparsequota.c,v 1.2 1999/12/06 13:21:05 mrsam Exp $";
14
15int maildir_parsequota(const char *n, unsigned long *s)
16{
17const char *o;
18int yes;
19
20 if ((o=strrchr(n, '/')) == 0) o=n;
21
22 for (; *o; o++)
23 if (*o == ':') break;
24 yes=0;
25 for ( ; o >= n; --o)
26 {
27 if (*o == '/') break;
28
29 if (*o == ',' && o[1] == 'S' && o[2] == '=')
30 {
31 yes=1;
32 o += 3;
33 break;
34 }
35 }
36 if (yes)
37 {
38 *s=0;
39 while (*o >= '0' && *o <= '9')
40 *s= *s*10 + (*o++ - '0');
41 return (0);
42 }
43 return (-1);
44}
diff --git a/maildirquota.c b/maildirquota.c
new file mode 100644
index 0000000..e9ba47b
--- /dev/null
+++ b/maildirquota.c
@@ -0,0 +1,685 @@
1/*
2** Copyright 1998 - 2002 Double Precision, Inc.
3** See COPYING for distribution information.
4*/
5
6#if HAVE_CONFIG_H
7#include "config.h"
8#endif
9
10#include <sys/types.h>
11/* #if HAVE_DIRENT_H */
12#include <dirent.h>
13#define NAMLEN(dirent) strlen((dirent)->d_name)
14/* #else
15#define dirent direct
16#define NAMLEN(dirent) (dirent)->d_namlen
17#if HAVE_SYS_NDIR_H
18#include <sys/ndir.h>
19#endif
20#if HAVE_SYS_DIR_H
21#include <sys/dir.h>
22#endif
23#if HAVE_NDIR_H
24#include <ndir.h>
25#endif
26#endif */
27#include <sys/types.h>
28/* #if HAVE_SYS_STAT_H */
29#include <sys/stat.h>
30/* #endif */
31#include <sys/uio.h>
32
33#include "maildirquota.h"
34#include "maildirmisc.h"
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <errno.h>
39/* #if HAVE_FCNTL_H */
40#include <fcntl.h>
41/* #endif */
42#if HAVE_UNISTD_H
43#include <unistd.h>
44#endif
45#include <time.h>
46#include "numlib.h"
47
48static const char rcsid[]="$Id: maildirquota.c,v 1.9 2002/05/01 04:05:33 mrsam Exp $";
49
50/* Read the maildirsize file */
51
52int maildirsize_read(const char *filename, /* The filename */
53 int *fdptr, /* Keep the file descriptor open */
54 off_t *sizeptr, /* Grand total of maildir size */
55 unsigned *cntptr, /* Grand total of message count */
56 unsigned *nlines, /* # of lines in maildirsize */
57 struct stat *statptr) /* The stats on maildirsize */
58{
59char buf[5120];
60int f;
61char *p;
62unsigned l;
63int n;
64int first;
65
66 if ((f=maildir_safeopen(filename, O_RDWR|O_APPEND, 0)) < 0)
67 return (-1);
68 p=buf;
69 l=sizeof(buf);
70
71 while (l)
72 {
73 n=read(f, p, l);
74 if (n < 0)
75 {
76 close(f);
77 return (-1);
78 }
79 if (n == 0) break;
80 p += n;
81 l -= n;
82 }
83 if (l == 0 || fstat(f, statptr)) /* maildir too big */
84 {
85 close(f);
86 return (-1);
87 }
88
89 *sizeptr=0;
90 *cntptr=0;
91 *nlines=0;
92 *p=0;
93 p=buf;
94 first=1;
95 while (*p)
96 {
97 long n=0;
98 int c=0;
99 char *q=p;
100
101 while (*p)
102 if (*p++ == '\n')
103 {
104 p[-1]=0;
105 break;
106 }
107
108 if (first)
109 {
110 first=0;
111 continue;
112 }
113 sscanf(q, "%ld %d", &n, &c);
114 *sizeptr += n;
115 *cntptr += c;
116 ++ *nlines;
117 }
118 *fdptr=f;
119 return (0);
120}
121
122static char *makenewmaildirsizename(const char *, int *);
123static int countcurnew(const char *, time_t *, off_t *, unsigned *);
124static int countsubdir(const char *, const char *,
125 time_t *, off_t *, unsigned *);
126static int statcurnew(const char *, time_t *);
127static int statsubdir(const char *, const char *, time_t *);
128
129#define MDQUOTA_SIZE 'S' /* Total size of all messages in maildir */
130#define MDQUOTA_BLOCKS 'B' /* Total # of blocks for all messages in
131 maildir -- NOT IMPLEMENTED */
132#define MDQUOTA_COUNT 'C' /* Total number of messages in maildir */
133
134static int qcalc(off_t s, unsigned n, const char *quota, int *percentage)
135{
136off_t i;
137int spercentage=0;
138int npercentage=0;
139
140 errno=ENOSPC;
141 while (quota && *quota)
142 {
143 int x=1;
144
145 if (*quota < '0' || *quota > '9')
146 {
147 ++quota;
148 continue;
149 }
150 i=0;
151 while (*quota >= '0' && *quota <= '9')
152 i=i*10 + (*quota++ - '0');
153 switch (*quota) {
154 default:
155 if (i < s)
156 {
157 *percentage=100;
158 return (-1);
159 }
160
161 /*
162 ** For huge quotas, over 20mb,
163 ** divide numerator & denominator by 1024 to prevent
164 ** an overflow when multiplying by 100
165 */
166
167 x=1;
168 if (i > 20000000) x=1024;
169
170 spercentage = i ? (s/x) * 100 / (i/x):100;
171 break;
172 case 'C':
173
174 if (i < n)
175 {
176 *percentage=100;
177 return (-1);
178 }
179
180 /* Ditto */
181
182 x=1;
183 if (i > 20000000) x=1024;
184
185 npercentage = i ? ((off_t)n/x) * 100 / (i/x):100;
186 break;
187 }
188 }
189 *percentage = spercentage > npercentage ? spercentage:npercentage;
190 return (0);
191}
192
193static int doaddquota(const char *, int, const char *, long, int, int);
194
195static int docheckquota(const char *dir,
196 int *maildirsize_fdptr,
197 const char *quota_type,
198 long xtra_size,
199 int xtra_cnt, int *percentage);
200
201
202int maildir_checkquota(const char *dir,
203 int *maildirsize_fdptr,
204 const char *quota_type,
205 long xtra_size,
206 int xtra_cnt)
207{
208int dummy;
209
210 return (docheckquota(dir, maildirsize_fdptr, quota_type,
211 xtra_size, xtra_cnt, &dummy));
212}
213
214int maildir_readquota(const char *dir, const char *quota_type)
215{
216int percentage=0;
217int fd=-1;
218
219 (void)docheckquota(dir, &fd, quota_type, 0, 0, &percentage);
220 if (fd >= 0)
221 close(fd);
222 return (percentage);
223}
224
225static int docheckquota(const char *dir,
226 int *maildirsize_fdptr,
227 const char *quota_type,
228 long xtra_size,
229 int xtra_cnt,
230 int *percentage)
231{
232char *checkfolder=(char *)malloc(strlen(dir)+sizeof("/maildirfolder"));
233char *newmaildirsizename;
234struct stat stat_buf;
235int maildirsize_fd;
236off_t maildirsize_size;
237unsigned maildirsize_cnt;
238unsigned maildirsize_nlines;
239int n;
240time_t tm;
241time_t maxtime;
242DIR *dirp;
243struct dirent *de;
244
245 if (checkfolder == 0) return (-1);
246 *maildirsize_fdptr= -1;
247 strcat(strcpy(checkfolder, dir), "/maildirfolder");
248 if (stat(checkfolder, &stat_buf) == 0) /* Go to parent */
249 {
250 strcat(strcpy(checkfolder, dir), "/..");
251 n=docheckquota(checkfolder, maildirsize_fdptr,
252 quota_type, xtra_size, xtra_cnt, percentage);
253 free(checkfolder);
254 return (n);
255 }
256 if (!quota_type || !*quota_type) return (0);
257
258 strcat(strcpy(checkfolder, dir), "/maildirsize");
259 time(&tm);
260 if (maildirsize_read(checkfolder, &maildirsize_fd,
261 &maildirsize_size, &maildirsize_cnt,
262 &maildirsize_nlines, &stat_buf) == 0)
263 {
264 n=qcalc(maildirsize_size+xtra_size, maildirsize_cnt+xtra_cnt,
265 quota_type, percentage);
266
267 if (n == 0)
268 {
269 free(checkfolder);
270 *maildirsize_fdptr=maildirsize_fd;
271 return (0);
272 }
273 close(maildirsize_fd);
274
275 if (maildirsize_nlines == 1 && tm < stat_buf.st_mtime + 15*60)
276 return (n);
277 }
278
279 maxtime=0;
280 maildirsize_size=0;
281 maildirsize_cnt=0;
282
283 if (countcurnew(dir, &maxtime, &maildirsize_size, &maildirsize_cnt))
284 {
285 free(checkfolder);
286 return (-1);
287 }
288
289 dirp=opendir(dir);
290 while (dirp && (de=readdir(dirp)) != 0)
291 {
292 if (countsubdir(dir, de->d_name, &maxtime, &maildirsize_size,
293 &maildirsize_cnt))
294 {
295 free(checkfolder);
296 closedir(dirp);
297 return (-1);
298 }
299 }
300 if (dirp)
301 {
302#if CLOSEDIR_VOID
303 closedir(dirp);
304#else
305 if (closedir(dirp))
306 {
307 free(checkfolder);
308 return (-1);
309 }
310#endif
311 }
312
313 newmaildirsizename=makenewmaildirsizename(dir, &maildirsize_fd);
314 if (!newmaildirsizename)
315 {
316 free(checkfolder);
317 return (-1);
318 }
319
320 *maildirsize_fdptr=maildirsize_fd;
321
322 if (doaddquota(dir, maildirsize_fd, quota_type, maildirsize_size,
323 maildirsize_cnt, 1))
324 {
325 free(newmaildirsizename);
326 unlink(newmaildirsizename);
327 close(maildirsize_fd);
328 *maildirsize_fdptr= -1;
329 free(checkfolder);
330 return (-1);
331 }
332
333 strcat(strcpy(checkfolder, dir), "/maildirsize");
334
335 if (rename(newmaildirsizename, checkfolder))
336 {
337 free(checkfolder);
338 unlink(newmaildirsizename);
339 close(maildirsize_fd);
340 *maildirsize_fdptr= -1;
341 }
342 free(checkfolder);
343 free(newmaildirsizename);
344
345 tm=0;
346
347 if (statcurnew(dir, &tm))
348 {
349 close(maildirsize_fd);
350 *maildirsize_fdptr= -1;
351 return (-1);
352 }
353
354 dirp=opendir(dir);
355 while (dirp && (de=readdir(dirp)) != 0)
356 {
357 if (statsubdir(dir, de->d_name, &tm))
358 {
359 close(maildirsize_fd);
360 *maildirsize_fdptr= -1;
361 closedir(dirp);
362 return (-1);
363 }
364 }
365 if (dirp)
366 {
367#if CLOSEDIR_VOID
368 closedir(dirp);
369#else
370 if (closedir(dirp))
371 {
372 close(maildirsize_fd);
373 *maildirsize_fdptr= -1;
374 return (-1);
375 }
376#endif
377 }
378
379 if (tm != maxtime) /* Race condition, someone changed something */
380 {
381 errno=EAGAIN;
382 return (-1);
383 }
384
385 return (qcalc(maildirsize_size+xtra_size, maildirsize_cnt+xtra_cnt,
386 quota_type, percentage));
387}
388
389int maildir_addquota(const char *dir, int maildirsize_fd,
390 const char *quota_type, long maildirsize_size, int maildirsize_cnt)
391{
392 if (!quota_type || !*quota_type) return (0);
393 return (doaddquota(dir, maildirsize_fd, quota_type, maildirsize_size,
394 maildirsize_cnt, 0));
395}
396
397static int doaddquota(const char *dir, int maildirsize_fd,
398 const char *quota_type, long maildirsize_size, int maildirsize_cnt,
399 int isnew)
400{
401union {
402 char buf[100];
403 struct stat stat_buf;
404 } u; /* Scrooge */
405char *newname2=0;
406char *newmaildirsizename=0;
407struct iovec iov[3];
408int niov;
409struct iovec *p;
410int n;
411
412 niov=0;
413 if ( maildirsize_fd < 0)
414 {
415 newname2=(char *)malloc(strlen(dir)+sizeof("/maildirfolder"));
416 if (!newname2) return (-1);
417 strcat(strcpy(newname2, dir), "/maildirfolder");
418 if (stat(newname2, &u.stat_buf) == 0)
419 {
420 strcat(strcpy(newname2, dir), "/..");
421 n=doaddquota(newname2, maildirsize_fd, quota_type,
422 maildirsize_size, maildirsize_cnt,
423 isnew);
424 free(newname2);
425 return (n);
426 }
427
428 strcat(strcpy(newname2, dir), "/maildirsize");
429
430 if ((maildirsize_fd=maildir_safeopen(newname2,
431 O_RDWR|O_APPEND, 0644)) < 0)
432 {
433 newmaildirsizename=makenewmaildirsizename(dir, &maildirsize_fd);
434 if (!newmaildirsizename)
435 {
436 free(newname2);
437 return (-1);
438 }
439
440 maildirsize_fd=maildir_safeopen(newmaildirsizename,
441 O_CREAT|O_RDWR|O_APPEND, 0644);
442
443 if (maildirsize_fd < 0)
444 {
445 free(newname2);
446 return (-1);
447 }
448 isnew=1;
449 }
450 }
451
452 if (isnew)
453 {
454 iov[0].iov_base=(caddr_t)quota_type;
455 iov[0].iov_len=strlen(quota_type);
456 iov[1].iov_base=(caddr_t)"\n";
457 iov[1].iov_len=1;
458 niov=2;
459 }
460
461
462 sprintf(u.buf, "%ld %d\n", maildirsize_size, maildirsize_cnt);
463 iov[niov].iov_base=(caddr_t)u.buf;
464 iov[niov].iov_len=strlen(u.buf);
465
466 p=iov;
467 ++niov;
468 n=0;
469 while (niov)
470 {
471 if (n)
472 {
473 if (n < p->iov_len)
474 {
475 p->iov_base=
476 (caddr_t)((char *)p->iov_base + n);
477 p->iov_len -= n;
478 }
479 else
480 {
481 n -= p->iov_len;
482 ++p;
483 --niov;
484 continue;
485 }
486 }
487
488 n=writev( maildirsize_fd, p, niov);
489
490 if (n <= 0)
491 {
492 if (newname2)
493 {
494 close(maildirsize_fd);
495 free(newname2);
496 }
497 return (-1);
498 }
499 }
500 if (newname2)
501 {
502 close(maildirsize_fd);
503
504 if (newmaildirsizename)
505 {
506 rename(newmaildirsizename, newname2);
507 free(newmaildirsizename);
508 }
509 free(newname2);
510 }
511 return (0);
512}
513
514/* New maildirsize is built in the tmp subdirectory */
515
516static char *makenewmaildirsizename(const char *dir, int *fd)
517{
518char hostname[256];
519struct stat stat_buf;
520time_t t;
521char *p;
522
523 hostname[0]=0;
524 hostname[sizeof(hostname)-1]=0;
525 gethostname(hostname, sizeof(hostname)-1);
526 p=(char *)malloc(strlen(dir)+strlen(hostname)+130);
527 if (!p) return (0);
528
529 for (;;)
530 {
531 char tbuf[NUMBUFSIZE];
532 char pbuf[NUMBUFSIZE];
533
534 time(&t);
535 strcat(strcpy(p, dir), "/tmp/");
536 sprintf(p+strlen(p), "%s.%s_NeWmAiLdIrSiZe.%s",
537 str_time_t(t, tbuf),
538 str_pid_t(getpid(), pbuf), hostname);
539
540 if (stat( (const char *)p, &stat_buf) < 0 &&
541 (*fd=maildir_safeopen(p,
542 O_CREAT|O_RDWR|O_APPEND, 0644)) >= 0)
543 break;
544 sleep(3);
545 }
546 return (p);
547}
548
549static int statcurnew(const char *dir, time_t *maxtimestamp)
550{
551char *p=(char *)malloc(strlen(dir)+5);
552struct stat stat_buf;
553
554 if (!p) return (-1);
555 strcat(strcpy(p, dir), "/cur");
556 if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp)
557 *maxtimestamp=stat_buf.st_mtime;
558 strcat(strcpy(p, dir), "/new");
559 if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp)
560 *maxtimestamp=stat_buf.st_mtime;
561 free(p);
562 return (0);
563}
564
565static int statsubdir(const char *dir, const char *subdir, time_t *maxtime)
566{
567char *p;
568int n;
569
570 if ( *subdir != '.' || strcmp(subdir, ".") == 0 ||
571 strcmp(subdir, "..") == 0 || strcmp(subdir, "." TRASH) == 0)
572 return (0);
573
574 p=(char *)malloc(strlen(dir)+strlen(subdir)+2);
575 if (!p) return (-1);
576 strcat(strcat(strcpy(p, dir), "/"), subdir);
577 n=statcurnew(p, maxtime);
578 free(p);
579 return (n);
580}
581
582static int docount(const char *, time_t *, off_t *, unsigned *);
583
584static int countcurnew(const char *dir, time_t *maxtime,
585 off_t *sizep, unsigned *cntp)
586{
587char *p=(char *)malloc(strlen(dir)+5);
588int n;
589
590 if (!p) return (-1);
591 strcat(strcpy(p, dir), "/new");
592 n=docount(p, maxtime, sizep, cntp);
593 if (n == 0)
594 {
595 strcat(strcpy(p, dir), "/cur");
596 n=docount(p, maxtime, sizep, cntp);
597 }
598 free(p);
599 return (n);
600}
601
602static int countsubdir(const char *dir, const char *subdir, time_t *maxtime,
603 off_t *sizep, unsigned *cntp)
604{
605char *p;
606int n;
607
608 if ( *subdir != '.' || strcmp(subdir, ".") == 0 ||
609 strcmp(subdir, "..") == 0 || strcmp(subdir, "." TRASH) == 0)
610 return (0);
611
612 p=(char *)malloc(strlen(dir)+strlen(subdir)+2);
613 if (!p) return (2);
614 strcat(strcat(strcpy(p, dir), "/"), subdir);
615 n=countcurnew(p, maxtime, sizep, cntp);
616 free(p);
617 return (n);
618}
619
620static int docount(const char *dir, time_t *dirstamp,
621 off_t *sizep, unsigned *cntp)
622{
623struct stat stat_buf;
624char *p;
625DIR *dirp;
626struct dirent *de;
627unsigned long s;
628
629 if (stat(dir, &stat_buf)) return (0); /* Ignore */
630 if (stat_buf.st_mtime > *dirstamp) *dirstamp=stat_buf.st_mtime;
631 if ((dirp=opendir(dir)) == 0) return (0);
632 while ((de=readdir(dirp)) != 0)
633 {
634 const char *n=de->d_name;
635
636 if (*n == '.') continue;
637
638 /* PATCH - do not count msgs marked as deleted */
639
640 for ( ; *n; n++)
641 {
642 if (n[0] != ':' || n[1] != '2' ||
643 n[2] != ',') continue;
644 n += 3;
645 while (*n >= 'A' && *n <= 'Z')
646 {
647 if (*n == 'T') break;
648 ++n;
649 }
650 break;
651 }
652 if (*n == 'T') continue;
653 n=de->d_name;
654
655
656 if (maildir_parsequota(n, &s) == 0)
657 stat_buf.st_size=s;
658 else
659 {
660 p=(char *)malloc(strlen(dir)+strlen(n)+2);
661 if (!p)
662 {
663 closedir(dirp);
664 return (-1);
665 }
666 strcat(strcat(strcpy(p, dir), "/"), n);
667 if (stat(p, &stat_buf))
668 {
669 free(p);
670 continue;
671 }
672 free(p);
673 }
674 *sizep += stat_buf.st_size;
675 ++*cntp;
676 }
677
678#if CLOSEDIR_VOID
679 closedir(dirp);
680#else
681 if (closedir(dirp))
682 return (-1);
683#endif
684 return (0);
685}
diff --git a/maildirquota.h b/maildirquota.h
new file mode 100644
index 0000000..96bbea7
--- /dev/null
+++ b/maildirquota.h
@@ -0,0 +1,45 @@
1#ifndef maildirquota_h
2#define maildirquota_h
3
4/*
5** Copyright 1998 - 1999 Double Precision, Inc.
6** See COPYING for distribution information.
7*/
8
9#if HAVE_CONFIG_H
10#include "config.h"
11#endif
12
13#include <sys/types.h>
14#include <stdio.h>
15
16#ifdef __cplusplus
17extern "C" {
18#endif
19
20static const char maildirquota_h_rcsid[]="$Id: maildirquota.h,v 1.2 2000/09/04 17:10:28 mrsam Exp $";
21
22int maildir_checkquota(const char *, /* Pointer to directory */
23 int *, /* Initialized to -1, or opened descriptor for maildirsize */
24 const char *, /* The quota */
25 long, /* Extra bytes planning to add/remove from maildir */
26 int); /* Extra messages planning to add/remove from maildir */
27
28int maildir_addquota(const char *, /* Pointer to the maildir */
29 int, /* Must be the int pointed to by 2nd arg to checkquota */
30 const char *, /* The quota */
31 long, /* +/- bytes */
32 int); /* +/- files */
33
34int maildir_readquota(const char *, /* Directory */
35 const char *); /* Quota, from getquota */
36
37int maildir_parsequota(const char *, unsigned long *);
38 /* Attempt to parse file size encoded in filename. Returns 0 if
39 ** parsed, non-zero if we didn't parse. */
40
41#ifdef __cplusplus
42}
43#endif
44
45#endif
diff --git a/numlib.h b/numlib.h
new file mode 100644
index 0000000..d36a791
--- /dev/null
+++ b/numlib.h
@@ -0,0 +1,45 @@
1#ifndef numlib_h
2#define numlib_h
3
4/*
5** Copyright 1998 - 1999 Double Precision, Inc.
6** See COPYING for distribution information.
7*/
8
9#ifdef __cplusplus
10extern "C" {
11#endif
12
13static const char numlib_h_rcsid[]="$Id: numlib.h,v 1.3 2001/08/12 15:46:40 mrsam Exp $";
14
15#if HAVE_CONFIG_H
16#include "config.h"
17#endif
18
19#include <sys/types.h>
20#include <time.h>
21
22#define NUMBUFSIZE 60
23
24/* Convert various system types to decimal */
25
26char *str_time_t(time_t, char *);
27char *str_off_t(off_t, char *);
28char *str_pid_t(pid_t, char *);
29char *str_ino_t(ino_t, char *);
30char *str_uid_t(uid_t, char *);
31char *str_gid_t(gid_t, char *);
32char *str_size_t(size_t, char *);
33
34char *str_sizekb(unsigned long, char *); /* X Kb or X Mb */
35
36/* Convert selected system types to hex */
37
38char *strh_time_t(time_t, char *);
39char *strh_pid_t(pid_t, char *);
40char *strh_ino_t(ino_t, char *);
41
42#ifdef __cplusplus
43}
44#endif
45#endif
diff --git a/overmaildirquota.c b/overmaildirquota.c
new file mode 100644
index 0000000..5e1877c
--- /dev/null
+++ b/overmaildirquota.c
@@ -0,0 +1,43 @@
1/*
2** Copyright 1998 - 1999 Double Precision, Inc.
3** See COPYING for distribution information.
4*/
5
6#if HAVE_CONFIG_H
7#include "config.h"
8#endif
9#include "maildirquota.h"
10#include <stdlib.h>
11#include <string.h>
12#include <errno.h>
13#include <sys/stat.h>
14
15static const char rcsid[]="$Id: overquota.c,v 1.0 2002/06/09 16:21:05 mr \
16sam Exp $";
17
18
19int user_over_maildirquota( const char *dir, const char *q)
20{
21struct stat stat_buf;
22int quotafd;
23int ret_value;
24
25 if (fstat(0, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode) &&
26 stat_buf.st_size > 0 && *q)
27 {
28 if (maildir_checkquota(dir, &quotafd, q, stat_buf.st_size, 1)
29 && errno != EAGAIN)
30 {
31 if (quotafd >= 0) close(quotafd);
32 ret_value = 1;
33 } else {
34 maildir_addquota(dir, quotafd, q, stat_buf.st_size, 1);
35 if (quotafd >= 0) close(quotafd);
36 ret_value = 0;
37 }
38 } else {
39 ret_value = 0;
40 }
41
42 return(ret_value);
43}
diff --git a/qmail-local.c b/qmail-local.c
index 6fec288..1bafb34 100644
--- a/qmail-local.c
+++ b/qmail-local.c
@@ -66,6 +66,7 @@ stralloc foo = {0};
66 66
67char buf[1024]; 67char buf[1024];
68char outbuf[1024]; 68char outbuf[1024];
69#define QUOTABUFSIZE 256
69 70
70/* child process */ 71/* child process */
71 72
@@ -86,9 +87,15 @@ char *dir;
86 int fd; 87 int fd;
87 substdio ss; 88 substdio ss;
88 substdio ssout; 89 substdio ssout;
90 char quotabuf[QUOTABUFSIZE];
89 91
90 sig_alarmcatch(sigalrm); 92 sig_alarmcatch(sigalrm);
91 if (chdir(dir) == -1) { if (error_temp(errno)) _exit(1); _exit(2); } 93 if (chdir(dir) == -1) { if (error_temp(errno)) _exit(1); _exit(2); }
94 if (maildir_getquota(dir, quotabuf) == 0) {
95 if (user_over_maildirquota(dir,quotabuf)==1) {
96 _exit(1);
97 }
98 }
92 pid = getpid(); 99 pid = getpid();
93 host[0] = 0; 100 host[0] = 0;
94 gethostname(host,sizeof(host)); 101 gethostname(host,sizeof(host));
@@ -99,7 +106,10 @@ char *dir;
99 s += fmt_str(s,"tmp/"); 106 s += fmt_str(s,"tmp/");
100 s += fmt_ulong(s,time); *s++ = '.'; 107 s += fmt_ulong(s,time); *s++ = '.';
101 s += fmt_ulong(s,pid); *s++ = '.'; 108 s += fmt_ulong(s,pid); *s++ = '.';
102 s += fmt_strn(s,host,sizeof(host)); *s++ = 0; 109 s += fmt_strn(s,host,sizeof(host));
110 s += fmt_strn(s,",S=",sizeof(",S="));
111 if (fstat(0,&st) == -1) if (errno == error_noent) break;
112 s += fmt_ulong(s,st.st_size); *s++ = 0;
103 if (stat(fntmptph,&st) == -1) if (errno == error_noent) break; 113 if (stat(fntmptph,&st) == -1) if (errno == error_noent) break;
104 /* really should never get to this point */ 114 /* really should never get to this point */
105 if (loop == 2) _exit(1); 115 if (loop == 2) _exit(1);
@@ -159,6 +169,7 @@ char *fn;
159 switch(wait_exitcode(wstat)) 169 switch(wait_exitcode(wstat))
160 { 170 {
161 case 0: break; 171 case 0: break;
172 case 1: strerr_die1x(1, "User over quota. (#5.1.1)");
162 case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)"); 173 case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)");
163 case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)"); 174 case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)");
164 case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)"); 175 case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)");
diff --git a/qmail-pop3d.c b/qmail-pop3d.c
index 51976c2..d2a6f87 100644
--- a/qmail-pop3d.c
+++ b/qmail-pop3d.c
@@ -16,6 +16,11 @@
16#include "readwrite.h" 16#include "readwrite.h"
17#include "timeoutread.h" 17#include "timeoutread.h"
18#include "timeoutwrite.h" 18#include "timeoutwrite.h"
19#include <errno.h>
20#include "maildirquota.h"
21#include "maildirmisc.h"
22
23#define QUOTABUFSIZE 256
19 24
20void die() { _exit(0); } 25void die() { _exit(0); }
21 26
@@ -45,19 +50,15 @@ void put(buf,len) char *buf; int len;
45{ 50{
46 substdio_put(&ssout,buf,len); 51 substdio_put(&ssout,buf,len);
47} 52}
48void puts(s) char *s;
49{
50 substdio_puts(&ssout,s);
51}
52void flush() 53void flush()
53{ 54{
54 substdio_flush(&ssout); 55 substdio_flush(&ssout);
55} 56}
56void err(s) char *s; 57void err(s) char *s;
57{ 58{
58 puts("-ERR "); 59 substdio_puts(&ssout,"-ERR ");
59 puts(s); 60 substdio_puts(&ssout,s);
60 puts("\r\n"); 61 substdio_puts(&ssout,"\r\n");
61 flush(); 62 flush();
62} 63}
63 64
@@ -73,7 +74,7 @@ void err_toobig() { err("not that many messages"); }
73void err_nosuch() { err("unable to open that message"); } 74void err_nosuch() { err("unable to open that message"); }
74void err_nounlink() { err("unable to unlink all deleted messages"); } 75void err_nounlink() { err("unable to unlink all deleted messages"); }
75 76
76void okay() { puts("+OK \r\n"); flush(); } 77void okay() { substdio_puts(&ssout,"+OK \r\n"); flush(); }
77 78
78void printfn(fn) char *fn; 79void printfn(fn) char *fn;
79{ 80{
@@ -153,11 +154,11 @@ void pop3_stat()
153 154
154 total = 0; 155 total = 0;
155 for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size; 156 for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size;
156 puts("+OK "); 157 substdio_puts(&ssout,"+OK ");
157 put(strnum,fmt_uint(strnum,numm)); 158 put(strnum,fmt_uint(strnum,numm));
158 puts(" "); 159 substdio_puts(&ssout," ");
159 put(strnum,fmt_ulong(strnum,total)); 160 put(strnum,fmt_ulong(strnum,total));
160 puts("\r\n"); 161 substdio_puts(&ssout,"\r\n");
161 flush(); 162 flush();
162} 163}
163 164
@@ -171,18 +172,41 @@ void pop3_rset()
171 172
172void pop3_last() 173void pop3_last()
173{ 174{
174 puts("+OK "); 175 substdio_puts(&ssout,"+OK ");
175 put(strnum,fmt_uint(strnum,last)); 176 put(strnum,fmt_uint(strnum,last));
176 puts("\r\n"); 177 substdio_puts(&ssout,"\r\n");
177 flush(); 178 flush();
178} 179}
179 180
180void pop3_quit() 181void pop3_quit()
181{ 182{
182 int i; 183 int i;
184 char quotabuf[QUOTABUFSIZE];
185 int has_quota=maildir_getquota(".", quotabuf);
186
187 long deleted_bytes=0;
188 long deleted_messages=0;
189
183 for (i = 0;i < numm;++i) 190 for (i = 0;i < numm;++i)
184 if (m[i].flagdeleted) { 191 if (m[i].flagdeleted) {
185 if (unlink(m[i].fn) == -1) err_nounlink(); 192 unsigned long un=0;
193 const char *filename=m[i].fn;
194 if (has_quota == 0 && !MAILDIR_DELETED(filename)) {
195 if (maildir_parsequota(filename, &un)) {
196 struct stat stat_buf;
197
198 if (stat(filename, &stat_buf) == 0)
199 un=stat_buf.st_size;
200 }
201 }
202 if (unlink(m[i].fn) == -1) {
203 err_nounlink();
204 un=0;
205 }
206 if (un) {
207 deleted_bytes -= un;
208 deleted_messages -= 1;
209 }
186 } 210 }
187 else 211 else
188 if (str_start(m[i].fn,"new/")) { 212 if (str_start(m[i].fn,"new/")) {
@@ -192,6 +216,21 @@ void pop3_quit()
192 if (!stralloc_0(&line)) die_nomem(); 216 if (!stralloc_0(&line)) die_nomem();
193 rename(m[i].fn,line.s); /* if it fails, bummer */ 217 rename(m[i].fn,line.s); /* if it fails, bummer */
194 } 218 }
219
220 if (deleted_messages < 0) {
221 int quotafd;
222
223 if (maildir_checkquota(".", &quotafd, quotabuf, deleted_bytes,
224 deleted_messages) && errno != EAGAIN &&
225 deleted_bytes >= 0)
226 {
227 if (quotafd >= 0) close (quotafd);
228 } else {
229 maildir_addquota(".", quotafd, quotabuf,
230 deleted_bytes, deleted_messages);
231 if (quotafd >= 0) close(quotafd);
232 }
233 }
195 okay(); 234 okay();
196 die(); 235 die();
197} 236}
@@ -222,10 +261,10 @@ int i;
222int flaguidl; 261int flaguidl;
223{ 262{
224 put(strnum,fmt_uint(strnum,i + 1)); 263 put(strnum,fmt_uint(strnum,i + 1));
225 puts(" "); 264 substdio_puts(&ssout," ");
226 if (flaguidl) printfn(m[i].fn); 265 if (flaguidl) printfn(m[i].fn);
227 else put(strnum,fmt_ulong(strnum,m[i].size)); 266 else put(strnum,fmt_ulong(strnum,m[i].size));
228 puts("\r\n"); 267 substdio_puts(&ssout,"\r\n");
229} 268}
230 269
231void dolisting(arg,flaguidl) char *arg; int flaguidl; 270void dolisting(arg,flaguidl) char *arg; int flaguidl;
@@ -234,7 +273,7 @@ void dolisting(arg,flaguidl) char *arg; int flaguidl;
234 if (*arg) { 273 if (*arg) {
235 i = msgno(arg); 274 i = msgno(arg);
236 if (i == -1) return; 275 if (i == -1) return;
237 puts("+OK "); 276 substdio_puts(&ssout,"+OK ");
238 list(i,flaguidl); 277 list(i,flaguidl);
239 } 278 }
240 else { 279 else {
@@ -242,7 +281,7 @@ void dolisting(arg,flaguidl) char *arg; int flaguidl;
242 for (i = 0;i < numm;++i) 281 for (i = 0;i < numm;++i)
243 if (!m[i].flagdeleted) 282 if (!m[i].flagdeleted)
244 list(i,flaguidl); 283 list(i,flaguidl);
245 puts(".\r\n"); 284 substdio_puts(&ssout,".\r\n");
246 } 285 }
247 flush(); 286 flush();
248} 287}
diff --git a/strpidt.c b/strpidt.c
new file mode 100644
index 0000000..7bec6b3
--- /dev/null
+++ b/strpidt.c
@@ -0,0 +1,26 @@
1/*
2** Copyright 1998 - 2000 Double Precision, Inc.
3** See COPYING for distribution information.
4*/
5
6#if HAVE_CONFIG_H
7#include "config.h"
8#endif
9#include "numlib.h"
10#include <string.h>
11
12static const char rcsid[]="$Id: strpidt.c,v 1.3 2000/05/27 04:59:26 mrsam Exp $";
13
14char *str_pid_t(pid_t t, char *arg)
15{
16char buf[NUMBUFSIZE];
17char *p=buf+sizeof(buf)-1;
18
19 *p=0;
20 do
21 {
22 *--p= '0' + (t % 10);
23 t=t / 10;
24 } while(t);
25 return (strcpy(arg, p));
26}
diff --git a/strtimet.c b/strtimet.c
new file mode 100644
index 0000000..c174872
--- /dev/null
+++ b/strtimet.c
@@ -0,0 +1,26 @@
1/*
2** Copyright 1998 - 2000 Double Precision, Inc.
3** See COPYING for distribution information.
4*/
5
6#if HAVE_CONFIG_H
7#include "config.h"
8#endif
9#include "numlib.h"
10#include <string.h>
11
12static const char rcsid[]="$Id: strtimet.c,v 1.3 2000/05/27 04:59:26 mrsam Exp $";
13
14char *str_time_t(time_t t, char *arg)
15{
16char buf[NUMBUFSIZE];
17char *p=buf+sizeof(buf)-1;
18
19 *p=0;
20 do
21 {
22 *--p= '0' + (t % 10);
23 t=t / 10;
24 } while(t);
25 return (strcpy(arg, p));
26}