#include <sys_defs.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <msg.h>
#include <htable.h>
#include <vstring.h>
#include <vstream.h>
#include <deliver_flock.h>
#include <set_eugid.h>
#include <mail_copy.h>
#include <bounce.h>
#include <defer.h>
#include <sent.h>
#include <been_here.h>
#include <mail_params.h>
#include <mbox_conf.h>
#include <mbox_open.h>
#include "local.h"
#define STR vstring_str
int deliver_file(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
{
char *myname = "deliver_file";
struct stat st;
MBOX *mp;
VSTRING *why;
int mail_copy_status = MAIL_COPY_STAT_WRITE;
int deliver_status;
int copy_flags;
state.level++;
if (msg_verbose)
MSG_LOG_STATE(myname, state);
if (been_here(state.dup_filter, "file %ld %s", (long) usr_attr.uid, path))
return (0);
if ((local_file_deliver_mask & state.msg_attr.exp_type) == 0)
return (bounce_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
"mail to file is restricted"));
if (usr_attr.uid == 0 && (usr_attr.uid = var_default_uid) == 0)
msg_panic("privileged default user id");
if (usr_attr.gid == 0 && (usr_attr.gid = var_default_gid) == 0)
msg_panic("privileged default group id");
if (path[strlen(path) - 1] == '/')
return (deliver_maildir(state, usr_attr, path));
if (msg_verbose)
msg_info("deliver_file (%ld,%ld): %s",
(long) usr_attr.uid, (long) usr_attr.gid, path);
if (vstream_fseek(state.msg_attr.fp, state.msg_attr.offset, SEEK_SET) < 0)
msg_fatal("seek queue file %s: %m", state.msg_attr.queue_id);
why = vstring_alloc(100);
copy_flags = MAIL_COPY_MBOX;
if ((local_deliver_hdr_mask & DELIVER_HDR_FILE) == 0)
copy_flags &= ~MAIL_COPY_DELIVERED;
set_eugid(usr_attr.uid, usr_attr.gid);
mp = mbox_open(path, O_APPEND | O_CREAT | O_WRONLY,
S_IRUSR | S_IWUSR, &st, -1, -1,
local_mbox_lock_mask | MBOX_DOT_LOCK_MAY_FAIL, why);
if (mp != 0) {
if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
vstream_fclose(mp->fp);
vstring_sprintf(why, "destination file is executable");
errno = 0;
} else {
mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), mp->fp,
S_ISREG(st.st_mode) ? copy_flags :
(copy_flags & ~MAIL_COPY_TOFILE),
"\n", why);
}
mbox_release(mp);
}
set_eugid(var_owner_uid, var_owner_gid);
if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) {
deliver_status = DEL_STAT_DEFER;
} else if (mail_copy_status != 0) {
deliver_status = (errno == EAGAIN || errno == ENOSPC || errno == ESTALE ?
defer_append : bounce_append)
(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
"cannot append message to destination file %s: %s",
path, STR(why));
} else {
deliver_status = sent(SENT_ATTR(state.msg_attr), "%s", path);
}
vstring_free(why);
return (deliver_status);
}