Exemple #1
0
static int savemessage(const char *extension, const char *sender,
		const char *receipient,
		FILE *f, const char *name,
		const char *ufromline,
		const char *dtline,
		const char *rpline,
		const char *quota)
{
FILE	*delivf;
char	buf[BUFSIZ];
int	c;
static unsigned counter=0;
struct	stat stat_buf;
struct maildirsize quotainfo;
struct maildir_tmpcreate_info createInfo;

	umask(077);

	if ((delivf=fopen(name, "a")) != 0)
	{
		/* Ok, perhaps this is a mailbox */

		struct ll_mail *ll=ll_mail_alloc(name);

		fclose(delivf);

		if (!ll)
		{
			delivery_error(name);	/* I Give up */
		}

		while ((mbox_fd=ll_mail_open(ll)) < 0)
		{
			switch (errno) {
			case EEXIST:
			case EAGAIN:
				sleep(5);
				continue;
				break;
			}

			delivery_error(name);
		}

		delivf=fdopen(mbox_fd, "w");

		if (delivf == NULL || fseek(delivf, 0L, SEEK_END) < 0
		    || (mbox_size=ftell(delivf)) == (off_t)-1)
		{
			if (delivf)
				fclose(delivf);
			close(mbox_fd);
			ll_mail_free(ll);
			delivery_error(name);	/* I Give up */
		}

		signal(SIGHUP, truncmbox);
		signal(SIGINT, truncmbox);
		signal(SIGQUIT, truncmbox);
		signal(SIGTERM, truncmbox);

		fprintf(delivf, "%s\n%s\n%s\n",
			ufromline,
			dtline,
			rpline);

		while (fgets(buf, sizeof(buf), f) != 0)
		{
		char	*q=buf;

			while (*q == '>')	q++;
			if (strncmp(q, "From ", 5) == 0)
				putc('>', delivf);
			fprintf(delivf, "%s", buf);
			if (strchr(buf, '\n') == 0)
			{
				while ((c=getc(f)) >= 0)
				{
					putc(c, delivf);
					if (c == '\n')	break;
				}
			}
		}

		if ( ferror(f) || fflush(delivf) || ferror(delivf)
#if	EXPLICITSYNC
			|| fsync(fileno(delivf))
#endif
			||
				(signal(SIGHUP, SIG_DFL),
				signal(SIGINT, SIG_DFL),
				signal(SIGQUIT, SIG_DFL),
				signal(SIGTERM, SIG_DFL),
				fclose(delivf))
			)
		{
#if	HAVE_FTRUNCATE
			if (ftruncate(mbox_fd, mbox_size) < 0)
				; /* ignore */
#endif
			close(mbox_fd);
			ll_mail_free(ll);
			delivery_error("mailbox.close");
		}
		close(mbox_fd);
		ll_mail_free(ll);
		return (0);
	}

	if (fstat(fileno(f), &stat_buf))
	{
		delivery_error("stat");
		return (-1);
	}

	stat_buf.st_size += strlen(dtline) + strlen(rpline) + 2;

	if (maildir_quota_add_start(name, &quotainfo, stat_buf.st_size, 1,
				    quota && *quota != 0 ? quota:NULL))
	{
		errno=ENOSPC;
		delivery_error("out of memory.");
	}

	maildir_closequotafile(&quotainfo);	/* For now. */

	sprintf(buf, "%u", ++counter);

	maildir_tmpcreate_init(&createInfo);
	createInfo.maildir=name;
	createInfo.uniq=buf;
	createInfo.msgsize=stat_buf.st_size;
	createInfo.doordie=1;

	if ((delivf=maildir_tmpcreate_fp(&createInfo)) == NULL)
	{
		snprintf(buf, BUFSIZ-1,
			 "maildir.open: %s: %s", name,
			 strerror(errno));
		buf[BUFSIZ-1] = 0;
		delivery_error(buf);
		return (-1);
	}

	fprintf(delivf, "%s\n%s\n", dtline, rpline);

	{
		char buffer[BUFSIZ];
		int n;

		while ((n=fread(buffer, 1, sizeof(buffer), f)) > 0)
			if (fwrite(buffer, 1, n, delivf)  != n)
				break;
	}

	if ( ferror(f) || fflush(delivf) || ferror(delivf)
#if	EXPLICITSYNC
			|| fsync(fileno(delivf))
#endif
			|| fclose(delivf)
			|| (delivf=0, maildir_movetmpnew(createInfo.tmpname,
							 createInfo.newname)))
	{
		snprintf(buf, BUFSIZ-1,
			 "maildir.close: %s: %s", name,
			 strerror(errno));
		buf[BUFSIZ-1] = 0;

		if (delivf)	fclose(delivf);
		unlink(createInfo.newname);
		delivery_error(buf);
		return (-1);
	}

#if EXPLICITDIRSYNC

	{
		int fd;

		strcpy(strrchr(createInfo.newname, '/')+1, ".");

		fd=open(createInfo.newname, O_RDONLY);

		if (fd >= 0)
		{
			fsync(fd);
			close(fd);
		}
	}
#endif

	maildir_tmpcreate_free(&createInfo);

	maildir_quota_deleted(name, stat_buf.st_size, 1);
	return (0);
}
Exemple #2
0
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);
}