Logo Search packages:      
Sourcecode: maildrop version File versions  Download package

deliverquota.c

/*
** Copyright 1998 - 2003 Double Precision, Inc.
** See COPYING for distribution information.
*/

#include    "config.h"
#include    "maildirquota.h"
#include    "maildircreate.h"
#include    "maildirmisc.h"
#include    "quotawarnmsg.h"
#include    <stdio.h>
#include    <string.h>
#include    <stdlib.h>
#include    <sys/types.h>
#include    <errno.h>
#if HAVE_SYS_STAT_H
#include    <sys/stat.h>
#endif
#if HAVE_UNISTD_H
#include    <unistd.h>
#endif
#if   HAVE_FCNTL_H
#include    <fcntl.h>
#endif
#include    <time.h>
#if   HAVE_SYSEXITS_H
#include    <sysexits.h>
#endif
#include    "rfc822/rfc822.h"
#ifndef     BUFSIZE
#define     BUFSIZE     8192
#endif

#ifndef     EX_OSERR
#define     EX_OSERR    71
#endif

#ifndef     EX_IOERR
#define     EX_IOERR    74
#endif

#ifndef     EX_TEMPFAIL
#define EX_TEMPFAIL     75
#endif

#ifndef     EX_NOPERM
#define     EX_NOPERM   77
#endif

static const char rcsid[]="$Id: deliverquota.c,v 1.21 2003/01/20 13:47:19 mrsam Exp $";

static long deliver(int fdin, const char *dir, long s,
                int auto_create, int quota_warn_percent, const char *pfix,
                const char *newquota)
{
      struct maildir_tmpcreate_info createInfo;
      char  buf[BUFSIZ];
      int   n;
      long  ss=0;
      int   fd;

      maildir_tmpcreate_init(&createInfo);

      createInfo.maildir=dir;
      createInfo.uniq=pfix;
      createInfo.msgsize=s;
      createInfo.doordie=1;

      while ((fd=maildir_tmpcreate_fd(&createInfo)) < 0)
      {
            if (errno == ENOENT && auto_create && maildir_mkdir(dir) == 0)
            {
                  auto_create=0;
                  continue;
            }

            perror(dir);
            exit(EX_TEMPFAIL);
      }

      while ((n=read(fdin, buf, sizeof(buf))) > 0)
      {
      char  *p=buf;

            ss += n;
            while (n)
            {
            int   l;

                  if ((l=write(fd, p, n)) < 0)
                  {
                        close(fd);
                        unlink(createInfo.tmpname);
                        perror(createInfo.tmpname);
                        exit(EX_IOERR);
                  }
                  p += l;
                  n -= l;
            }
      }
      close(fd);
      if (n < 0)
      {
            unlink(createInfo.tmpname);
            perror(createInfo.tmpname);
            exit(EX_IOERR);
      }

      if (s != ss)
      {
            char  *qq;
            struct maildirsize info;

            if (s)      *strrchr(createInfo.newname, ',')=0;
            /* Zap incorrect size */
            qq=malloc(strlen(createInfo.newname)+100);
            if (!qq)
            {
                  unlink(createInfo.tmpname);
                  perror(createInfo.tmpname);
                  exit(EX_OSERR);
            }
            sprintf(qq, "%s,S=%ld", createInfo.newname, ss-s);
            free(createInfo.newname);
            createInfo.newname=qq;

            if (maildirquota_countfolder(dir))
            {
                  if (maildir_quota_add_start(dir, &info, ss-s, 1,
                                        newquota))
                  {
                        unlink(createInfo.tmpname);
                        printf("Mail quota exceeded.\n");
                        exit(EX_NOPERM);
                  }
                  maildir_quota_add_end(&info, ss-s, 1);
            }
      }

      if (maildir_movetmpnew(createInfo.tmpname, createInfo.newname))
      {
            unlink(createInfo.tmpname);
            perror(createInfo.tmpname);
            exit(EX_IOERR);
      }
      maildir_tmpcreate_free(&createInfo);

      if (quota_warn_percent >= 0)
            maildir_deliver_quota_warning(dir, quota_warn_percent);

      return (ss);
}

int main(int argc, char **argv)
{
      const char *dir;
      struct      stat  stat_buf;
      int   auto_create = 0;
      int   quota_warn_percent = -1;
      int i;
      const char *quota=NULL;

      for (i=1; i<argc; i++)
      {
            if (strcmp(argv[i], "-c") == 0)
            {
                  auto_create = 1;
                  continue;
            }

            if (strcmp(argv[i], "-w") == 0 && argc - i > 1)
            {
                  quota_warn_percent = atoi(argv[i+1]);
                  ++i;
                  continue;
            }
            break;
      }
      if (i >= argc || quota_warn_percent < -1 || quota_warn_percent > 100)
      {
            fprintf(stderr, "Usage: %s [-c] [-w percent] maildir\n",
                  argv[0]);
            exit(73);
      }

      dir=argv[i];

      ++i;
      if (i < argc)
            quota=argv[i];

      if (fstat(0, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode) &&
            stat_buf.st_size > 0)
      {
            struct maildirsize info;
            int doquota=maildirquota_countfolder(dir);

            if (doquota &&
                maildir_quota_add_start(dir, &info, stat_buf.st_size, 1,
                                  quota))
            {
                  if (quota_warn_percent >= 0)
                        maildir_deliver_quota_warning(dir, quota_warn_percent);
                  printf("Mail quota exceeded.\n");
                  exit(77);
            }
            deliver(0, dir, stat_buf.st_size,
                  auto_create, quota_warn_percent, NULL, quota);

            if (doquota)
                  maildir_quota_add_end(&info, stat_buf.st_size, 1);
            exit(0);
      }
      deliver(0, dir, 0, auto_create, quota_warn_percent, NULL, quota);
      exit(0);
}

Generated by  Doxygen 1.6.0   Back to index