diff options
| author | manuel <manuel@mausz.at> | 2013-02-04 02:48:34 +0100 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2013-02-04 02:48:34 +0100 |
| commit | 5d47a7101a2394c7f7bb288585464fa293a2ad33 (patch) | |
| tree | 0c371687c8791b2278c5b8049bbd64a7de1d0863 | |
| parent | 86d5a6ec30ceea44e9459394d2e6403642cdd158 (diff) | |
| download | qmail-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-- | Makefile | 45 | ||||
| -rw-r--r-- | TARGETS | 8 | ||||
| -rw-r--r-- | maildirflags.c | 23 | ||||
| -rw-r--r-- | maildirgetquota.c | 50 | ||||
| -rw-r--r-- | maildirgetquota.h | 30 | ||||
| -rw-r--r-- | maildirmisc.h | 145 | ||||
| -rw-r--r-- | maildiropen.c | 133 | ||||
| -rw-r--r-- | maildirparsequota.c | 44 | ||||
| -rw-r--r-- | maildirquota.c | 685 | ||||
| -rw-r--r-- | maildirquota.h | 45 | ||||
| -rw-r--r-- | numlib.h | 45 | ||||
| -rw-r--r-- | overmaildirquota.c | 43 | ||||
| -rw-r--r-- | qmail-local.c | 13 | ||||
| -rw-r--r-- | qmail-pop3d.c | 75 | ||||
| -rw-r--r-- | strpidt.c | 26 | ||||
| -rw-r--r-- | strtimet.c | 26 |
16 files changed, 1413 insertions, 23 deletions
| @@ -894,6 +894,38 @@ datetime.h gen_alloc.h stralloc.h gen_alloc.h str.h exit.h hfield.h \ | |||
| 894 | readwrite.h open.h headerbody.h maildir.h strerr.h | 894 | readwrite.h open.h headerbody.h maildir.h strerr.h |
| 895 | ./compile maildirwatch.c | 895 | ./compile maildirwatch.c |
| 896 | 896 | ||
| 897 | maildirgetquota.o: \ | ||
| 898 | compile maildirgetquota.c maildirgetquota.h maildirmisc.h | ||
| 899 | ./compile maildirgetquota.c | ||
| 900 | |||
| 901 | maildirflags.o: \ | ||
| 902 | compile maildirflags.c | ||
| 903 | ./compile maildirflags.c | ||
| 904 | |||
| 905 | maildiropen.o: \ | ||
| 906 | compile maildiropen.c maildirmisc.h | ||
| 907 | ./compile maildiropen.c | ||
| 908 | |||
| 909 | maildirparsequota.o: \ | ||
| 910 | compile maildirparsequota.c | ||
| 911 | ./compile maildirparsequota.c | ||
| 912 | |||
| 913 | maildirquota.o: \ | ||
| 914 | compile maildirquota.c maildirquota.h maildirmisc.h numlib.h | ||
| 915 | ./compile maildirquota.c | ||
| 916 | |||
| 917 | overmaildirquota.o: \ | ||
| 918 | compile overmaildirquota.c | ||
| 919 | ./compile overmaildirquota.c | ||
| 920 | |||
| 921 | strtimet.o: \ | ||
| 922 | compile strtimet.c | ||
| 923 | ./compile strtimet.c | ||
| 924 | |||
| 925 | strpidt.o: \ | ||
| 926 | compile strpidt.c | ||
| 927 | ./compile strpidt.c | ||
| 928 | |||
| 897 | mailsubj: \ | 929 | mailsubj: \ |
| 898 | warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split | 930 | warn-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: \ | |||
| 1178 | load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \ | 1210 | load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \ |
| 1179 | slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \ | 1211 | slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \ |
| 1180 | wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \ | 1212 | wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \ |
| 1181 | fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib | 1213 | fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib maildirquota.o \ |
| 1214 | maildirgetquota.o maildiropen.o maildirparsequota.o overmaildirquota.o \ | ||
| 1215 | strtimet.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 | ||
| 1188 | qmail-local.0: \ | 1223 | qmail-local.0: \ |
| 1189 | qmail-local.8 | 1224 | qmail-local.8 |
| @@ -1273,11 +1308,13 @@ readwrite.h open.h error.h case.h auto_qmail.h | |||
| 1273 | qmail-pop3d: \ | 1308 | qmail-pop3d: \ |
| 1274 | load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \ | 1309 | load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \ |
| 1275 | maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \ | 1310 | maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \ |
| 1276 | stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib | 1311 | stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib maildirquota.o \ |
| 1312 | maildirparsequota.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 | ||
| 1282 | qmail-pop3d.0: \ | 1319 | qmail-pop3d.0: \ |
| 1283 | qmail-pop3d.8 | 1320 | qmail-pop3d.8 |
| @@ -16,6 +16,14 @@ myctime.o | |||
| 16 | slurpclose.o | 16 | slurpclose.o |
| 17 | make-makelib | 17 | make-makelib |
| 18 | makelib | 18 | makelib |
| 19 | maildirflags.o | ||
| 20 | maildirparsequota.o | ||
| 21 | maildiropen.o | ||
| 22 | maildirgetquota.o | ||
| 23 | maildirquota.o | ||
| 24 | overmaildirquota.o | ||
| 25 | strtimet.o | ||
| 26 | strpidt.o | ||
| 19 | case_diffb.o | 27 | case_diffb.o |
| 20 | case_diffs.o | 28 | case_diffs.o |
| 21 | case_lowerb.o | 29 | case_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 | |||
| 9 | static const char rcsid[]="$Id: maildirflags.c,v 1.1 2000/10/07 01:10:19 mrsam Exp $"; | ||
| 10 | |||
| 11 | int 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 | |||
| 17 | int maildir_getquota(const char *dir, char buf[QUOTABUFSIZE]) | ||
| 18 | { | ||
| 19 | char *p; | ||
| 20 | struct stat stat_buf; | ||
| 21 | int n; | ||
| 22 | int 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 | ||
| 17 | extern "C" { | ||
| 18 | #endif | ||
| 19 | |||
| 20 | static 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 | |||
| 24 | int 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 | ||
| 14 | extern "C" { | ||
| 15 | #endif | ||
| 16 | |||
| 17 | static 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 | |||
| 34 | char *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 | |||
| 41 | char *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 | |||
| 50 | int 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 | |||
| 66 | int 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 | |||
| 76 | int maildir_mkdir(const char *); /* directory */ | ||
| 77 | /* | ||
| 78 | ** Create maildir including all subdirectories in the path (like mkdir -p) | ||
| 79 | */ | ||
| 80 | |||
| 81 | void maildir_purgetmp(const char *); /* maildir */ | ||
| 82 | /* purges old stuff out of tmp */ | ||
| 83 | |||
| 84 | void maildir_purge(const char *, /* directory */ | ||
| 85 | unsigned); /* time_t to purge */ | ||
| 86 | |||
| 87 | void maildir_getnew(const char *, /* maildir */ | ||
| 88 | const char *); /* folder */ | ||
| 89 | /* move messages from new to cur */ | ||
| 90 | |||
| 91 | int maildir_deletefolder(const char *, /* maildir */ | ||
| 92 | const char *); /* folder */ | ||
| 93 | /* deletes a folder */ | ||
| 94 | |||
| 95 | int maildir_mddelete(const char *); /* delete a maildir folder by path */ | ||
| 96 | |||
| 97 | void 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 | |||
| 102 | int maildir_shared_subscribe(const char *, /* maildir */ | ||
| 103 | const char *); /* folder */ | ||
| 104 | /* subscribe to a shared folder */ | ||
| 105 | |||
| 106 | void 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 | |||
| 111 | int maildir_shared_unsubscribe(const char *, /* maildir */ | ||
| 112 | const char *); /* folder */ | ||
| 113 | /* unsubscribe from a shared folder */ | ||
| 114 | |||
| 115 | char *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 | |||
| 122 | void maildir_shared_sync(const char *); /* maildir */ | ||
| 123 | /* "sync" the shared folder */ | ||
| 124 | |||
| 125 | int maildir_sharedisro(const char *); /* maildir */ | ||
| 126 | /* maildir is a shared read-only folder */ | ||
| 127 | |||
| 128 | int maildir_unlinksharedmsg(const char *); /* filename */ | ||
| 129 | /* Remove a message from a shared folder */ | ||
| 130 | |||
| 131 | /* Internal function that reads a symlink */ | ||
| 132 | |||
| 133 | char *maildir_getlink(const char *); | ||
| 134 | |||
| 135 | /* Determine whether the maildir filename has a certain flag */ | ||
| 136 | |||
| 137 | int 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 | |||
| 25 | static const char rcsid[]="$Id: maildiropen.c,v 1.7 2000/12/10 04:43:44 mrsam Exp $"; | ||
| 26 | |||
| 27 | char *maildir_getlink(const char *filename) | ||
| 28 | { | ||
| 29 | #if HAVE_READLINK | ||
| 30 | size_t bufsiz; | ||
| 31 | char *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 | |||
| 64 | int maildir_semisafeopen(const char *path, int mode, int perm) | ||
| 65 | { | ||
| 66 | |||
| 67 | #if HAVE_READLINK | ||
| 68 | |||
| 69 | char *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 | |||
| 105 | int maildir_safeopen(const char *path, int mode, int perm) | ||
| 106 | { | ||
| 107 | struct stat stat1, stat2; | ||
| 108 | |||
| 109 | int 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 | |||
| 13 | static const char rcsid[]="$Id: maildirparsequota.c,v 1.2 1999/12/06 13:21:05 mrsam Exp $"; | ||
| 14 | |||
| 15 | int maildir_parsequota(const char *n, unsigned long *s) | ||
| 16 | { | ||
| 17 | const char *o; | ||
| 18 | int 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 | |||
| 48 | static const char rcsid[]="$Id: maildirquota.c,v 1.9 2002/05/01 04:05:33 mrsam Exp $"; | ||
| 49 | |||
| 50 | /* Read the maildirsize file */ | ||
| 51 | |||
| 52 | int 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 | { | ||
| 59 | char buf[5120]; | ||
| 60 | int f; | ||
| 61 | char *p; | ||
| 62 | unsigned l; | ||
| 63 | int n; | ||
| 64 | int 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 | |||
| 122 | static char *makenewmaildirsizename(const char *, int *); | ||
| 123 | static int countcurnew(const char *, time_t *, off_t *, unsigned *); | ||
| 124 | static int countsubdir(const char *, const char *, | ||
| 125 | time_t *, off_t *, unsigned *); | ||
| 126 | static int statcurnew(const char *, time_t *); | ||
| 127 | static 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 | |||
| 134 | static int qcalc(off_t s, unsigned n, const char *quota, int *percentage) | ||
| 135 | { | ||
| 136 | off_t i; | ||
| 137 | int spercentage=0; | ||
| 138 | int 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 | |||
| 193 | static int doaddquota(const char *, int, const char *, long, int, int); | ||
| 194 | |||
| 195 | static 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 | |||
| 202 | int maildir_checkquota(const char *dir, | ||
| 203 | int *maildirsize_fdptr, | ||
| 204 | const char *quota_type, | ||
| 205 | long xtra_size, | ||
| 206 | int xtra_cnt) | ||
| 207 | { | ||
| 208 | int dummy; | ||
| 209 | |||
| 210 | return (docheckquota(dir, maildirsize_fdptr, quota_type, | ||
| 211 | xtra_size, xtra_cnt, &dummy)); | ||
| 212 | } | ||
| 213 | |||
| 214 | int maildir_readquota(const char *dir, const char *quota_type) | ||
| 215 | { | ||
| 216 | int percentage=0; | ||
| 217 | int 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 | |||
| 225 | static 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 | { | ||
| 232 | char *checkfolder=(char *)malloc(strlen(dir)+sizeof("/maildirfolder")); | ||
| 233 | char *newmaildirsizename; | ||
| 234 | struct stat stat_buf; | ||
| 235 | int maildirsize_fd; | ||
| 236 | off_t maildirsize_size; | ||
| 237 | unsigned maildirsize_cnt; | ||
| 238 | unsigned maildirsize_nlines; | ||
| 239 | int n; | ||
| 240 | time_t tm; | ||
| 241 | time_t maxtime; | ||
| 242 | DIR *dirp; | ||
| 243 | struct 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 | |||
| 389 | int 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 | |||
| 397 | static int doaddquota(const char *dir, int maildirsize_fd, | ||
| 398 | const char *quota_type, long maildirsize_size, int maildirsize_cnt, | ||
| 399 | int isnew) | ||
| 400 | { | ||
| 401 | union { | ||
| 402 | char buf[100]; | ||
| 403 | struct stat stat_buf; | ||
| 404 | } u; /* Scrooge */ | ||
| 405 | char *newname2=0; | ||
| 406 | char *newmaildirsizename=0; | ||
| 407 | struct iovec iov[3]; | ||
| 408 | int niov; | ||
| 409 | struct iovec *p; | ||
| 410 | int 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 | |||
| 516 | static char *makenewmaildirsizename(const char *dir, int *fd) | ||
| 517 | { | ||
| 518 | char hostname[256]; | ||
| 519 | struct stat stat_buf; | ||
| 520 | time_t t; | ||
| 521 | char *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 | |||
| 549 | static int statcurnew(const char *dir, time_t *maxtimestamp) | ||
| 550 | { | ||
| 551 | char *p=(char *)malloc(strlen(dir)+5); | ||
| 552 | struct 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 | |||
| 565 | static int statsubdir(const char *dir, const char *subdir, time_t *maxtime) | ||
| 566 | { | ||
| 567 | char *p; | ||
| 568 | int 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 | |||
| 582 | static int docount(const char *, time_t *, off_t *, unsigned *); | ||
| 583 | |||
| 584 | static int countcurnew(const char *dir, time_t *maxtime, | ||
| 585 | off_t *sizep, unsigned *cntp) | ||
| 586 | { | ||
| 587 | char *p=(char *)malloc(strlen(dir)+5); | ||
| 588 | int 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 | |||
| 602 | static int countsubdir(const char *dir, const char *subdir, time_t *maxtime, | ||
| 603 | off_t *sizep, unsigned *cntp) | ||
| 604 | { | ||
| 605 | char *p; | ||
| 606 | int 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 | |||
| 620 | static int docount(const char *dir, time_t *dirstamp, | ||
| 621 | off_t *sizep, unsigned *cntp) | ||
| 622 | { | ||
| 623 | struct stat stat_buf; | ||
| 624 | char *p; | ||
| 625 | DIR *dirp; | ||
| 626 | struct dirent *de; | ||
| 627 | unsigned 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 | ||
| 17 | extern "C" { | ||
| 18 | #endif | ||
| 19 | |||
| 20 | static const char maildirquota_h_rcsid[]="$Id: maildirquota.h,v 1.2 2000/09/04 17:10:28 mrsam Exp $"; | ||
| 21 | |||
| 22 | int 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 | |||
| 28 | int 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 | |||
| 34 | int maildir_readquota(const char *, /* Directory */ | ||
| 35 | const char *); /* Quota, from getquota */ | ||
| 36 | |||
| 37 | int 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 | ||
| 10 | extern "C" { | ||
| 11 | #endif | ||
| 12 | |||
| 13 | static 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 | |||
| 26 | char *str_time_t(time_t, char *); | ||
| 27 | char *str_off_t(off_t, char *); | ||
| 28 | char *str_pid_t(pid_t, char *); | ||
| 29 | char *str_ino_t(ino_t, char *); | ||
| 30 | char *str_uid_t(uid_t, char *); | ||
| 31 | char *str_gid_t(gid_t, char *); | ||
| 32 | char *str_size_t(size_t, char *); | ||
| 33 | |||
| 34 | char *str_sizekb(unsigned long, char *); /* X Kb or X Mb */ | ||
| 35 | |||
| 36 | /* Convert selected system types to hex */ | ||
| 37 | |||
| 38 | char *strh_time_t(time_t, char *); | ||
| 39 | char *strh_pid_t(pid_t, char *); | ||
| 40 | char *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 | |||
| 15 | static const char rcsid[]="$Id: overquota.c,v 1.0 2002/06/09 16:21:05 mr \ | ||
| 16 | sam Exp $"; | ||
| 17 | |||
| 18 | |||
| 19 | int user_over_maildirquota( const char *dir, const char *q) | ||
| 20 | { | ||
| 21 | struct stat stat_buf; | ||
| 22 | int quotafd; | ||
| 23 | int 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, "afd, 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 | ||
| 67 | char buf[1024]; | 67 | char buf[1024]; |
| 68 | char outbuf[1024]; | 68 | char 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 | ||
| 20 | void die() { _exit(0); } | 25 | void 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 | } |
| 48 | void puts(s) char *s; | ||
| 49 | { | ||
| 50 | substdio_puts(&ssout,s); | ||
| 51 | } | ||
| 52 | void flush() | 53 | void flush() |
| 53 | { | 54 | { |
| 54 | substdio_flush(&ssout); | 55 | substdio_flush(&ssout); |
| 55 | } | 56 | } |
| 56 | void err(s) char *s; | 57 | void 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"); } | |||
| 73 | void err_nosuch() { err("unable to open that message"); } | 74 | void err_nosuch() { err("unable to open that message"); } |
| 74 | void err_nounlink() { err("unable to unlink all deleted messages"); } | 75 | void err_nounlink() { err("unable to unlink all deleted messages"); } |
| 75 | 76 | ||
| 76 | void okay() { puts("+OK \r\n"); flush(); } | 77 | void okay() { substdio_puts(&ssout,"+OK \r\n"); flush(); } |
| 77 | 78 | ||
| 78 | void printfn(fn) char *fn; | 79 | void 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 | ||
| 172 | void pop3_last() | 173 | void 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 | ||
| 180 | void pop3_quit() | 181 | void 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(".", "afd, 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; | |||
| 222 | int flaguidl; | 261 | int 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 | ||
| 231 | void dolisting(arg,flaguidl) char *arg; int flaguidl; | 270 | void 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 | |||
| 12 | static const char rcsid[]="$Id: strpidt.c,v 1.3 2000/05/27 04:59:26 mrsam Exp $"; | ||
| 13 | |||
| 14 | char *str_pid_t(pid_t t, char *arg) | ||
| 15 | { | ||
| 16 | char buf[NUMBUFSIZE]; | ||
| 17 | char *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 | |||
| 12 | static const char rcsid[]="$Id: strtimet.c,v 1.3 2000/05/27 04:59:26 mrsam Exp $"; | ||
| 13 | |||
| 14 | char *str_time_t(time_t t, char *arg) | ||
| 15 | { | ||
| 16 | char buf[NUMBUFSIZE]; | ||
| 17 | char *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 | } | ||
