110 #include <sys/stat.h> 
  165 static QMGR_MESSAGE *qmgr_message_create(
const char *queue_name,
 
  166                            const char *queue_id, 
int qflags)
 
  256 static void qmgr_message_oldstyle_scan(
QMGR_MESSAGE *message)
 
  259     long    orig_offset, extra_offset;
 
  291         msg_info(
"old-style scan record %c %s", rec_type, start);
 
  304         if ((extra_offset = atol(start)) <= message->
data_offset)
 
  341     const char *error_text;
 
  349     int     have_log_client_attr = 0;
 
  371         msg_panic(
"%s: recipient list not empty on recipient reload",
 
  379     if (recipient_limit < message->rcpt_limit)
 
  383     if (recipient_limit > 5000)
 
  384     recipient_limit = 5000;
 
  385     if (recipient_limit <= 0)
 
  416     if (curr_offset == message->
data_offset && curr_offset > 0) {
 
  424         msg_info(
"record %c %s", rec_type, start);
 
  432         msg_warn(
"%s: message rejected: missing end record",
 
  448         if ((error_text = 
split_nameval(start, &name, &value)) != 0) {
 
  449         msg_warn(
"%s: ignoring bad attribute: %s: %.200s",
 
  450              message->
queue_id, error_text, start);
 
  468                    dsn_orcpt ? dsn_orcpt : 
"",
 
  469                    dsn_notify ? dsn_notify : 0,
 
  470                    orig_rcpt ? orig_rcpt : 
"", start);
 
  524         if (dsn_orcpt != 0) {
 
  525         msg_warn(
"%s: ignoring out-of-order DSN original recipient address <%.200s>",
 
  536         if (dsn_notify != 0) {
 
  537         msg_warn(
"%s: ignoring out-of-order DSN notify flags <%d>",
 
  543             msg_warn(
"%s: ignoring malformed DSN notify flags <%.200s>",
 
  552         if (orig_rcpt != 0) {
 
  553         msg_warn(
"%s: ignoring out-of-order original recipient <%.200s>",
 
  571         if ((count = sscanf(start, 
"%ld %ld %d %d %ld %d",
 
  578             msg_warn(
"%s: invalid size record: %.100s",
 
  584             msg_warn(
"%s: invalid flags in size record: %.100s",
 
  589         } 
else if (count == 1) {
 
  591             qmgr_message_oldstyle_scan(message);
 
  594             msg_warn(
"%s: message rejected: weird size record",
 
  604         msg_warn(
"%s: invalid size record: %.100s",
 
  640         if (message->
sender == 0) {
 
  657         msg_warn(
"%s: ignoring malformed DSN RET flags in queue file record:%.100s",
 
  685         if (have_log_client_attr == 0 && message->
client_name == 0)
 
  688         if (have_log_client_attr == 0 && message->
client_addr == 0)
 
  691         if (have_log_client_attr == 0 && message->
client_port == 0)
 
  694         if (have_log_client_attr == 0 && message->
client_proto == 0)
 
  697         if (have_log_client_attr == 0 && message->
client_helo == 0)
 
  705         have_log_client_attr = 1;
 
  710         have_log_client_attr = 1;
 
  715         have_log_client_attr = 1;
 
  720         have_log_client_attr = 1;
 
  725         have_log_client_attr = 1;
 
  730             msg_warn(
"%s: ignoring multiple %s attribute: %s",
 
  736             msg_warn(
"%s: ignoring multiple %s attribute: %s",
 
  742             msg_warn(
"%s: ignoring multiple %s attribute: %s",
 
  748             msg_warn(
"%s: ignoring multiple %s attribute: %s",
 
  754             msg_warn(
"%s: ignoring multiple %s attribute: %s",
 
  764         if (message->
tflags == 0) {
 
  786             msg_warn(
"%s: ignoring VERP request for null sender",
 
  789             msg_warn(
"%s: ignoring bad VERP request: \"%.100s\"",
 
  793             msg_info(
"%s: enabling VERP for sender \"%.100s\"",
 
  806     if (dsn_orcpt != 0) {
 
  808         msg_warn(
"%s: ignoring out-of-order DSN original recipient <%.200s>",
 
  812     if (orig_rcpt != 0) {
 
  814         msg_warn(
"%s: ignoring out-of-order original recipient <%.200s>",
 
  880     msg_warn(
"%s: rcpt count mismatch (%d)",
 
  887     msg_warn(
"%s: message rejected: missing arrival time record",
 
  889     } 
else if (message->
sender == 0) {
 
  890     msg_warn(
"%s: message rejected: missing sender record",
 
  893     msg_warn(
"%s: message rejected: missing size record",
 
  914     if (qmgr_message_open(message)
 
  920     qmgr_message_close(message);
 
  928     msg_panic(
"qmgr_message_kill_record: bad offset 0x%lx", offset);
 
  929     if (qmgr_message_open(message)
 
  933     qmgr_message_close(message);
 
  938 static int qmgr_message_sort_compare(
const void *p1, 
const void *p2)
 
  956     if (queue1 != 0 && queue2 == 0)
 
  958     if (queue1 == 0 && queue2 != 0)
 
  960     if (queue1 != 0 && queue2 != 0) {
 
  972     if ((result = strcmp(queue1->
name, queue2->
name)) != 0)
 
  979     at1 = strrchr(rcpt1->
address, 
'@');
 
  980     at2 = strrchr(rcpt2->
address, 
'@');
 
  981     if (at1 == 0 && at2 != 0)
 
  983     if (at1 != 0 && at2 == 0)
 
  985     if (at1 != 0 && at2 != 0
 
 1000       sizeof(message->
rcpt_list.
info[0]), qmgr_message_sort_compare);
 
 1005     msg_info(
"start sorted recipient list");
 
 1006     for (rcpt = list.
info; rcpt < list.
info + list.
len; rcpt++)
 
 1008     msg_info(
"end sorted recipient list");
 
 1017 #define QMGR_REDIRECT(rp, tp, np) do { \ 
 1019     vstring_strcpy((rp)->transport, (tp)); \ 
 1020     vstring_strcpy((rp)->nexthop, (np)); \ 
 1029               "4.3.0 address resolver failure");
 
 1033               "5.1.3 bad address syntax");
 
 1042 static void qmgr_message_resolve(
QMGR_MESSAGE *message)
 
 1044     static ARGV *defer_xport_argv;
 
 1060 #define STREQ(x,y)  (strcmp(x,y) == 0) 
 1061 #define STR     vstring_str 
 1062 #define LEN     VSTRING_LEN 
 1066     for (recipient = list.
info; recipient < list.
info + list.
len; recipient++) {
 
 1074         if (recipient > list.
info) {
 
 1084         if (qmgr_resolve_one(message, recipient,
 
 1085                  recipient->
address, &reply) < 0)
 
 1099 #define FILTER_WITHOUT_NEXTHOP(filter, next) \ 
 1100     (((next) = split_at((filter), ':')) == 0 || *(next) == 0) 
 1102 #define RCPT_WITHOUT_DOMAIN(rcpt, next) \ 
 1103     ((next = strrchr(rcpt, '@')) == 0 || *++(next) == 0) 
 1122         if (qmgr_resolve_one(message, recipient,
 
 1123                  recipient->
address, &reply) < 0)
 
 1134     if (recipient->
address[0] == 0) {
 
 1136               "5.1.3 null recipient address");
 
 1158             "undeliverable postmaster notification discarded"));
 
 1163             msg_warn(
"%s: undeliverable postmaster notification discarded",
 
 1167             message->
flags |= status;
 
 1177         if (defer_xport_argv == 0)
 
 1179         for (cpp = defer_xport_argv->
argv; *cpp; cpp++)
 
 1184                   "4.3.2 deferred transport");
 
 1194               "4.3.2 Too many address verification requests");
 
 1217         saved_dsn = transport->
dsn;
 
 1283     if (queue == 0 || !
STREQ(queue->
name, 
STR(queue_name))) {
 
 1300         saved_dsn = queue->
dsn;
 
 1310     recipient->
u.
queue = queue;
 
 1335 #define LIMIT_OK(limit, count) ((limit) == 0 || ((count) < (limit))) 
 1337     for (recipient = list.
info; recipient < list.
info + list.
len; recipient++) {
 
 1342     if ((queue = recipient->
u.
queue) == 0)
 
 1356     if (peer == 0 || queue != peer->
queue)
 
 1377     qmgr_recipient_count++;
 
 1403 static void qmgr_message_move_limits(
QMGR_MESSAGE *message)
 
 1420     msg_panic(
"qmgr_message_free: queue file is open");
 
 1463     myfree((
void *) message);
 
 1469                          int qflags, mode_t mode)
 
 1471     const char *myname = 
"qmgr_message_alloc";
 
 1475     msg_info(
"%s: %s %s", myname, queue_name, queue_id);
 
 1480     message = qmgr_message_create(queue_name, queue_id, qflags);
 
 1486 #define QMGR_LOCK_MODE (MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) 
 1488     if (qmgr_message_open(message) < 0) {
 
 1493     msg_info(
"%s: skipped, still being delivered", queue_id);
 
 1494     qmgr_message_close(message);
 
 1498     if (qmgr_message_read(message) < 0) {
 
 1499     qmgr_message_close(message);
 
 1523         msg_fatal(
"%s: %s: remove %s %s: %m", myname,
 
 1525     qmgr_message_sort(message);
 
 1526     qmgr_message_resolve(message);
 
 1527     qmgr_message_sort(message);
 
 1528     qmgr_message_assign(message);
 
 1529     qmgr_message_close(message);
 
 1531         qmgr_message_move_limits(message);
 
 1540     const char *myname = 
"qmgr_message_realloc";
 
 1555     if (qmgr_message_open(message) < 0)
 
 1557     if (qmgr_message_read(message) < 0) {
 
 1558     qmgr_message_close(message);
 
 1561     qmgr_message_sort(message);
 
 1562     qmgr_message_resolve(message);
 
 1563     qmgr_message_sort(message);
 
 1564     qmgr_message_assign(message);
 
 1565     qmgr_message_close(message);
 
 1567         qmgr_message_move_limits(message);
 
void qmgr_message_free(QMGR_MESSAGE *message)
QMGR_QUEUE * qmgr_error_queue(const char *, DSN *)
#define MAIL_ATTR_ACT_HELO_NAME
#define RESOLVE_FLAG_FAIL
int rec_put_type(VSTREAM *stream, int type, off_t offset)
void qmgr_job_free(QMGR_JOB *)
#define QMGR_READ_FLAG_MIXED_RCPT_OTHER
#define MAIL_ATTR_TRACE_FLAGS
char * mystrdup(const char *str)
#define MAIL_ATTR_ENCODING
#define MAIL_SERVICE_ERROR
QMGR_JOB_LIST message_peers
#define DSN_SIMPLE(dsn, _status, _reason)
NORETURN msg_panic(const char *fmt,...)
off_t vstream_ftell(VSTREAM *stream)
QMGR_TRANSPORT * qmgr_transport_create(const char *)
struct timeval active_time
#define FILTER_WITHOUT_NEXTHOP(filter, next)
void deliver_completed(VSTREAM *stream, long offset)
VSTRING * rewrite_clnt_internal(const char *ruleset, const char *addr, VSTRING *result)
int rec_goto(VSTREAM *stream, const char *buf)
QMGR_TRANSPORT * qmgr_error_transport(const char *)
#define MAIL_ATTR_RWR_CONTEXT
VSTRING * vstring_truncate(VSTRING *vp, ssize_t len)
QMGR_MESSAGE * qmgr_message_alloc(const char *queue_name, const char *queue_id, int qflags, mode_t mode)
void resolve_clnt_free(RESOLVE_REPLY *reply)
#define MAIL_ATTR_RWR_LOCAL
#define MAIL_ATTR_ACT_CLIENT_ADDR
#define QMGR_TRANSPORT_THROTTLED(t)
#define REC_TYPE_DSN_ENVID
QMGR_QUEUE * qmgr_queue_create(QMGR_TRANSPORT *, const char *, const char *)
#define MAIL_ATTR_SASL_METHOD
#define strcasecmp_utf8(s1, s2)
int alldig(const char *string)
QMGR_MESSAGE * qmgr_message_realloc(QMGR_MESSAGE *message)
#define MAIL_ATTR_LOG_HELO_NAME
const char * split_nameval(char *buf, char **name, char **value)
#define REC_TYPE_DSN_NOTIFY
#define MAIL_ATTR_LOG_PROTO_NAME
#define DEL_REQ_TRACE_FLAGS(f)
#define QMGR_LIST_INIT(head)
#define QMGR_READ_FLAG_SEEN_ALL_NON_RCPT
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
#define RESOLVE_CLASS_LOCAL
void qmgr_queue_unthrottle(QMGR_QUEUE *)
int rec_get_raw(VSTREAM *stream, VSTRING *buf, ssize_t maxsize, int flags)
VSTRING * vstring_sprintf_append(VSTRING *vp, const char *format,...)
struct timeval arrival_time
#define MAIL_ATTR_ACT_CLIENT_PORT
#define MAIL_ATTR_ENC_NONE
QMGR_JOB * qmgr_job_obtain(QMGR_MESSAGE *, QMGR_TRANSPORT *)
#define RESOLVE_FLAG_ERROR
QMGR_TRANSPORT * qmgr_transport_find(const char *)
#define REC_TYPE_DSN_ORCPT
void resolve_clnt_init(RESOLVE_REPLY *reply)
int var_qmgr_msg_rcpt_limit
char * var_double_bounce_sender
int vstream_fclose(VSTREAM *stream)
void opened(const char *queue_id, const char *sender, long size, int nrcpt, const char *fmt,...)
QMGR_PEER * qmgr_peer_obtain(QMGR_JOB *, QMGR_QUEUE *)
VSTREAM * mail_queue_open(const char *queue_name, const char *queue_id, int flags, mode_t mode)
#define MAIL_ATTR_SASL_SENDER
QMGR_QUEUE * qmgr_queue_find(QMGR_TRANSPORT *, const char *)
QMGR_ENTRY * qmgr_entry_create(QMGR_QUEUE *, QMGR_MESSAGE *)
void msg_warn(const char *fmt,...)
#define MAIL_ATTR_ACT_CLIENT_NAME
VSTRING * vstring_alloc(ssize_t len)
int myflock(int fd, int lock_style, int operation)
#define RCPT_LIST_INIT_QUEUE
#define RCPT_WITHOUT_DOMAIN(rcpt, next)
#define REC_TYPE_WARN_ARG(tv)
#define MAIL_ATTR_LOG_IDENT
#define MAIL_ATTR_LOG_CLIENT_ADDR
QMGR_TRANSPORT * transport
char * lowercase(char *string)
int rec_attr_map(const char *attr_name)
#define REC_TYPE_WARN_SCAN(cp, tv)
const char * verp_delims_verify(const char *delims)
#define QMGR_MSG_STATS(stats, message)
NORETURN msg_fatal(const char *fmt,...)
off_t vstream_fseek(VSTREAM *stream, off_t offset, int whence)
#define REC_TYPE_WARN_FORMAT
void qmgr_defer_recipient(QMGR_MESSAGE *, RECIPIENT *, DSN *)
QMGR_TRANSPORT * transport
int vstream_fflush(VSTREAM *stream)
void qmgr_transport_unthrottle(QMGR_TRANSPORT *)
char * var_def_filter_nexthop
#define MAIL_SERVICE_RETRY
int mail_queue_remove(const char *queue_name, const char *queue_id)
void recipient_list_init(RECIPIENT_LIST *list, int variant)
ARGV * argv_split(const char *, const char *)
void qmgr_message_kill_record(QMGR_MESSAGE *message, long offset)
#define MAIL_ATTR_SASL_USERNAME
#define QMGR_REDIRECT(rp, tp, np)
#define QMGR_READ_FLAG_DEFAULT
#define RECIPIENT_UPDATE(ptr, new)
#define QMGR_READ_FLAG_USER
#define resolve_clnt_verify_from(f, a, r)
#define strncasecmp_utf8(s1, s2, l)
#define MAIL_ATTR_LOG_CLIENT_NAME
VSTRING * vstring_free(VSTRING *vp)
void recipient_list_free(RECIPIENT_LIST *list)
char * qmgr_error_nexthop(DSN *)
void qmgr_message_update_warn(QMGR_MESSAGE *message)
#define vstream_fileno(vp)
#define resolve_clnt_query_from(f, a, r)
struct QMGR_QUEUE * queue
QMGR_JOB * candidate_cache_current
#define QMGR_MESSAGE_LOCKED
#define MAIL_ATTR_ACT_PROTO_NAME
int sent(int flags, const char *id, MSG_STATS *stats, RECIPIENT *recipient, const char *relay, DSN *dsn)
#define rec_get(fp, buf, limit)
void recipient_list_add(RECIPIENT_LIST *list, long offset, const char *dsn_orcpt, int dsn_notify, const char *orig_rcpt, const char *rcpt)
int rec_fprintf(VSTREAM *stream, int type, const char *format,...)
VSTRING * vstring_strncpy(VSTRING *vp, const char *src, ssize_t len)
QMGR_ENTRY_LIST entry_list
#define REC_TYPE_TIME_SCAN(cp, tv)
#define LIMIT_OK(limit, count)
#define DEL_REQ_FLAG_REC_DLY_SENT
void qmgr_job_move_limits(QMGR_JOB *)
#define DEL_REQ_FLAG_MTA_VRFY
int var_dsn_delay_cleared
#define MAIL_ATTR_LOG_CLIENT_PORT
#define QMGR_QUEUE_THROTTLED(q)
void * mymalloc(ssize_t len)
#define DEL_REQ_TRACE_ONLY_MASK
#define DEL_REQ_FLAG_RECORD
void msg_info(const char *fmt,...)