Back to index

courier  0.68.2
deliverquota.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2009 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include      "config.h"
00007 #include      "maildirquota.h"
00008 #include      "maildircreate.h"
00009 #include      "maildirmisc.h"
00010 #include      "quotawarnmsg.h"
00011 #include      <stdio.h>
00012 #include      <string.h>
00013 #include      <stdlib.h>
00014 #include      <sys/types.h>
00015 #include      <errno.h>
00016 #if HAVE_SYS_STAT_H
00017 #include      <sys/stat.h>
00018 #endif
00019 #if HAVE_UNISTD_H
00020 #include      <unistd.h>
00021 #endif
00022 #if    HAVE_FCNTL_H
00023 #include      <fcntl.h>
00024 #endif
00025 #include      <time.h>
00026 #if    HAVE_SYSEXITS_H
00027 #include      <sysexits.h>
00028 #endif
00029 #include      "rfc822/rfc822.h"
00030 #ifndef       BUFSIZE
00031 #define       BUFSIZE       8192
00032 #endif
00033 
00034 #ifndef       EX_OSERR
00035 #define       EX_OSERR      71
00036 #endif
00037 
00038 #ifndef       EX_IOERR
00039 #define       EX_IOERR      74
00040 #endif
00041 
00042 #ifndef       EX_TEMPFAIL
00043 #define EX_TEMPFAIL  75
00044 #endif
00045 
00046 #ifndef       EX_NOPERM
00047 #define       EX_NOPERM     77
00048 #endif
00049 
00050 
00051 static long deliver(int fdin, const char *dir, long s,
00052                   int auto_create, int quota_warn_percent, const char *pfix,
00053                   const char *newquota,
00054                   const char *quota_warn_msg)
00055 {
00056        struct maildir_tmpcreate_info createInfo;
00057        char   buf[BUFSIZ];
00058        int    n;
00059        long   ss=0;
00060        int    fd;
00061 
00062        maildir_tmpcreate_init(&createInfo);
00063        createInfo.openmode=0666;
00064        createInfo.maildir=dir;
00065        createInfo.uniq=pfix;
00066        createInfo.msgsize=s;
00067        createInfo.doordie=1;
00068 
00069        while ((fd=maildir_tmpcreate_fd(&createInfo)) < 0)
00070        {
00071               if (errno == ENOENT && auto_create && maildir_mkdir(dir) == 0)
00072               {
00073                      auto_create=0;
00074                      continue;
00075               }
00076 
00077               perror(dir);
00078               exit(EX_TEMPFAIL);
00079        }
00080 
00081        while ((n=read(fdin, buf, sizeof(buf))) > 0)
00082        {
00083        char   *p=buf;
00084 
00085               ss += n;
00086               while (n)
00087               {
00088               int    l;
00089 
00090                      if ((l=write(fd, p, n)) < 0)
00091                      {
00092                             close(fd);
00093                             unlink(createInfo.tmpname);
00094                             perror(createInfo.tmpname);
00095                             exit(EX_IOERR);
00096                      }
00097                      p += l;
00098                      n -= l;
00099               }
00100        }
00101        close(fd);
00102        if (n < 0)
00103        {
00104               unlink(createInfo.tmpname);
00105               perror(createInfo.tmpname);
00106               exit(EX_IOERR);
00107        }
00108 
00109        if (s != ss)
00110        {
00111               char   *qq;
00112               struct maildirsize info;
00113 
00114               if (s) *strrchr(createInfo.newname, ',')=0;
00115               /* Zap incorrect size */
00116               qq=malloc(strlen(createInfo.newname)+100);
00117               if (!qq)
00118               {
00119                      unlink(createInfo.tmpname);
00120                      perror(createInfo.tmpname);
00121                      exit(EX_OSERR);
00122               }
00123               sprintf(qq, "%s,S=%ld", createInfo.newname, ss-s);
00124               free(createInfo.newname);
00125               createInfo.newname=qq;
00126 
00127               if (maildirquota_countfolder(dir))
00128               {
00129                      if (maildir_quota_add_start(dir, &info, ss-s, 1,
00130                                               newquota))
00131                      {
00132                             unlink(createInfo.tmpname);
00133                             printf("Mail quota exceeded.\n");
00134 #if HAVE_COURIER
00135                             exit(EX_TEMPFAIL);
00136 #else
00137                             exit(EX_NOPERM);
00138 #endif
00139                      }
00140                      maildir_quota_add_end(&info, ss-s, 1);
00141               }
00142        }
00143 
00144        if (maildir_movetmpnew(createInfo.tmpname, createInfo.newname))
00145        {
00146               unlink(createInfo.tmpname);
00147               perror(createInfo.tmpname);
00148               exit(EX_IOERR);
00149        }
00150        maildir_tmpcreate_free(&createInfo);
00151 
00152        if (quota_warn_percent >= 0)
00153               maildir_deliver_quota_warning(dir, quota_warn_percent,
00154                                          quota_warn_msg);
00155 
00156        return (ss);
00157 }
00158 
00159 int main(int argc, char **argv)
00160 {
00161        const char *dir;
00162        struct stat   stat_buf;
00163        int    auto_create = 0;
00164        int    quota_warn_percent = -1;
00165        int i;
00166        const char *quota=NULL;
00167        const   char *quota_warn_msg=0;
00168 
00169        for (i=1; i<argc; i++)
00170        {
00171               if (strcmp(argv[i], "-c") == 0)
00172               {
00173                      auto_create = 1;
00174                      continue;
00175               }
00176 
00177               if (strcmp(argv[i], "-w") == 0 && argc - i > 1)
00178               {
00179                      quota_warn_percent = atoi(argv[i+1]);
00180                      ++i;
00181                      continue;
00182               }
00183 
00184               if (strcmp(argv[i], "-W") == 0 && argc - i > 1)
00185               {
00186                      quota_warn_msg = argv[i+1];
00187                      ++i;
00188                      continue;
00189               }
00190 
00191               break;
00192        }
00193        if (i >= argc || quota_warn_percent < -1 || quota_warn_percent > 100)
00194        {
00195               fprintf(stderr, "Usage: %s [-c] [-w percent] maildir\n",
00196                      argv[0]);
00197               exit(73);
00198        }
00199 
00200        dir=argv[i];
00201 
00202        ++i;
00203        if (i < argc)
00204               quota=argv[i];
00205 
00206        if (fstat(0, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode) &&
00207               stat_buf.st_size > 0)
00208        {
00209               struct maildirsize info;
00210               int doquota=maildirquota_countfolder(dir);
00211 
00212               if (doquota &&
00213                   maildir_quota_add_start(dir, &info, stat_buf.st_size, 1,
00214                                        quota))
00215               {
00216                      if (quota_warn_percent >= 0)
00217                             maildir_deliver_quota_warning(dir, quota_warn_percent,
00218                                                        quota_warn_msg);
00219                      printf("Mail quota exceeded.\n");
00220                      exit(77);
00221               }
00222               deliver(0, dir, stat_buf.st_size,
00223                      auto_create, quota_warn_percent, NULL, quota,
00224                      quota_warn_msg);
00225 
00226               if (doquota)
00227                      maildir_quota_add_end(&info, stat_buf.st_size, 1);
00228               exit(0);
00229        }
00230        deliver(0, dir, 0, auto_create, quota_warn_percent, NULL, quota,
00231               quota_warn_msg);
00232        exit(0);
00233 }