static int callback(struct authinfo *a, void *dummy) { struct maildirsize info; char mess[256]; if (maildir_openquotafile_init(&info, a->maildir) == 0) { if (atol(a->quota) - info.size.nbytes - getsize() >= 0 || atol(a->quota) == 0) { smtpd_access_policy("dunno"); } else { if (getsize() != 0) { sprintf(mess, "defer_if_permit Sorry, the user <%s> over quota, please try again later. Size messege: %d bytes. Free: %d bytes.", a->address, getsize(), atol(a->quota) - info.size.nbytes); } else { sprintf(mess, "defer_if_permit Sorry, the user <%s> over quota, please try again later.", a->address); } smtpd_access_policy(mess); } maildir_closequotafile(&info); } return (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, "ainfo, stat_buf.st_size, 1, quota && *quota != 0 ? quota:NULL)) { errno=ENOSPC; delivery_error("out of memory."); } maildir_closequotafile("ainfo); /* 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); }