postfix 1.1.11
check following for list of changes: ftp://ftp.porcupine.org/mirrors/postfix-release/official/postfix-1.1.11.RELEASE_NOTES
This commit is contained in:
parent
d7d4214831
commit
4a4a5f0782
|
@ -92,6 +92,7 @@ qmqpd.o: ../../include/namadr_list.h
|
|||
qmqpd.o: ../../include/match_list.h
|
||||
qmqpd.o: ../../include/match_ops.h
|
||||
qmqpd.o: ../../include/quote_822_local.h
|
||||
qmqpd.o: ../../include/quote_flags.h
|
||||
qmqpd.o: ../../include/match_parent_style.h
|
||||
qmqpd.o: ../../include/mail_server.h
|
||||
qmqpd.o: qmqpd.h
|
||||
|
|
|
@ -364,7 +364,7 @@ static void qmqpd_write_content(QMQPD_STATE *state)
|
|||
if (first) {
|
||||
if (strncmp(start + strspn(start, ">"), "From ", 5) == 0) {
|
||||
rec_fprintf(state->cleanup, rec_type,
|
||||
"Mailbox-Line: %*s", len, start);
|
||||
"X-Mailbox-Line: %*s", len, start);
|
||||
continue;
|
||||
}
|
||||
first = 0;
|
||||
|
|
|
@ -105,6 +105,10 @@
|
|||
/* .IP \fB-bs\fR
|
||||
/* Stand-alone SMTP server mode. Read SMTP commands from
|
||||
/* standard input, and write responses to standard output.
|
||||
/* In stand-alone SMTP server mode, UCE restrictions and
|
||||
/* access controls are disabled by default. To enable them,
|
||||
/* run the process as the \fBmail_owner\fR user.
|
||||
/* .sp
|
||||
/* This mode of operation is implemented by running the
|
||||
/* \fBsmtpd\fR(8) daemon.
|
||||
/* .IP "\fB-f \fIsender\fR"
|
||||
|
@ -363,6 +367,7 @@ static void enqueue(const int flags, const char *sender, const char *full_name,
|
|||
uid_t uid = getuid();
|
||||
int status;
|
||||
int naddr;
|
||||
int prev_type;
|
||||
|
||||
/*
|
||||
* Initialize.
|
||||
|
@ -453,8 +458,8 @@ static void enqueue(const int flags, const char *sender, const char *full_name,
|
|||
rec_fprintf(dst, REC_TYPE_MESG, REC_TYPE_MESG_FORMAT, 0L);
|
||||
skip_from_ = 1;
|
||||
strip_cr = STRIP_CR_DUNNO;
|
||||
while ((type = rec_streamlf_get(VSTREAM_IN, buf, var_line_limit))
|
||||
!= REC_TYPE_EOF) {
|
||||
for (prev_type = 0; (type = rec_streamlf_get(VSTREAM_IN, buf, var_line_limit))
|
||||
!= REC_TYPE_EOF; prev_type = type) {
|
||||
if (strip_cr == STRIP_CR_DUNNO && type == REC_TYPE_NORM) {
|
||||
if (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\r')
|
||||
strip_cr = STRIP_CR_DO;
|
||||
|
@ -472,7 +477,8 @@ static void enqueue(const int flags, const char *sender, const char *full_name,
|
|||
if (strip_cr == STRIP_CR_DO && type == REC_TYPE_NORM)
|
||||
if (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\r')
|
||||
vstring_truncate(buf, VSTRING_LEN(buf) - 1);
|
||||
if ((flags & SM_FLAG_AEOF) && VSTRING_LEN(buf) == 1 && *STR(buf) == '.')
|
||||
if ((flags & SM_FLAG_AEOF) && prev_type != REC_TYPE_CONT
|
||||
&& VSTRING_LEN(buf) == 1 && *STR(buf) == '.')
|
||||
break;
|
||||
if (REC_PUT_BUF(dst, type, buf) < 0)
|
||||
msg_fatal_status(EX_TEMPFAIL,
|
||||
|
|
|
@ -75,5 +75,8 @@ showq.o: ../../include/mail_scan_dir.h
|
|||
showq.o: ../../include/mail_conf.h
|
||||
showq.o: ../../include/record.h
|
||||
showq.o: ../../include/rec_type.h
|
||||
showq.o: ../../include/quote_822_local.h
|
||||
showq.o: ../../include/quote_flags.h
|
||||
showq.o: ../../include/mail_addr.h
|
||||
showq.o: ../../include/bounce_log.h
|
||||
showq.o: ../../include/mail_server.h
|
||||
|
|
|
@ -80,6 +80,8 @@
|
|||
#include <mail_conf.h>
|
||||
#include <record.h>
|
||||
#include <rec_type.h>
|
||||
#include <quote_822_local.h>
|
||||
#include <mail_addr.h>
|
||||
#include <bounce_log.h>
|
||||
|
||||
/* Single-threaded server skeleton. */
|
||||
|
@ -89,6 +91,7 @@
|
|||
/* Application-specific. */
|
||||
|
||||
int var_dup_filter_limit;
|
||||
char *var_empty_addr;
|
||||
|
||||
#define STRING_FORMAT "%-10s %8s %-20s %s\n"
|
||||
#define DATA_FORMAT "%-10s%c%8ld %20.20s %s\n"
|
||||
|
@ -96,10 +99,15 @@ int var_dup_filter_limit;
|
|||
|
||||
static void showq_reasons(VSTREAM *, BOUNCE_LOG *, HTABLE *);
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
|
||||
/* showq_report - report status of sender and recipients */
|
||||
|
||||
static void showq_report(VSTREAM *client, char *queue, char *id,
|
||||
VSTREAM *qfile, long size)
|
||||
{
|
||||
VSTRING *buf = vstring_alloc(100);
|
||||
VSTRING *printable_quoted_addr = vstring_alloc(100);
|
||||
int rec_type;
|
||||
time_t arrival_time = 0;
|
||||
char *start;
|
||||
|
@ -109,6 +117,13 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
|
|||
char status = (strcmp(queue, MAIL_QUEUE_ACTIVE) == 0 ? '*' : ' ');
|
||||
long offset;
|
||||
|
||||
/*
|
||||
* XXX addresses in defer logfiles are in printable quoted form, while
|
||||
* addresses in message envelope records are in raw unquoted form. This
|
||||
* may change once we replace the present ad-hoc bounce/defer logfile
|
||||
* format by one that is transparent for control etc. characters. See
|
||||
* also: bounce/bounce_append_service.c.
|
||||
*/
|
||||
while (!vstream_ferror(client) && (rec_type = rec_get(qfile, buf, 0)) > 0) {
|
||||
start = vstring_str(buf);
|
||||
switch (rec_type) {
|
||||
|
@ -121,18 +136,23 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
|
|||
break;
|
||||
case REC_TYPE_FROM:
|
||||
if (*start == 0)
|
||||
start = "(MAILER-DAEMON)";
|
||||
start = var_empty_addr;
|
||||
quote_822_local(printable_quoted_addr, start);
|
||||
printable(STR(printable_quoted_addr), '?');
|
||||
vstream_fprintf(client, DATA_FORMAT, id, status,
|
||||
msg_size > 0 ? msg_size : size, arrival_time > 0 ?
|
||||
asctime(localtime(&arrival_time)) : "??",
|
||||
printable(start, '?'));
|
||||
STR(printable_quoted_addr));
|
||||
break;
|
||||
case REC_TYPE_RCPT:
|
||||
if (*start == 0) /* can't happen? */
|
||||
start = "(MAILER-DAEMON)";
|
||||
if (dup_filter == 0 || htable_locate(dup_filter, start) == 0)
|
||||
start = var_empty_addr;
|
||||
quote_822_local(printable_quoted_addr, start);
|
||||
printable(STR(printable_quoted_addr), '?');
|
||||
if (dup_filter == 0
|
||||
|| htable_locate(dup_filter, STR(printable_quoted_addr)) == 0)
|
||||
vstream_fprintf(client, STRING_FORMAT,
|
||||
"", "", "", printable(start, '?'));
|
||||
"", "", "", STR(printable_quoted_addr));
|
||||
break;
|
||||
case REC_TYPE_MESG:
|
||||
if ((offset = atol(start)) > 0
|
||||
|
@ -163,6 +183,7 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
|
|||
}
|
||||
}
|
||||
vstring_free(buf);
|
||||
vstring_free(printable_quoted_addr);
|
||||
if (dup_filter)
|
||||
htable_free(dup_filter, (void (*) (char *)) 0);
|
||||
}
|
||||
|
@ -307,8 +328,13 @@ int main(int argc, char **argv)
|
|||
VAR_DUP_FILTER_LIMIT, DEF_DUP_FILTER_LIMIT, &var_dup_filter_limit, 0, 0,
|
||||
0,
|
||||
};
|
||||
CONFIG_STR_TABLE str_table[] = {
|
||||
VAR_EMPTY_ADDR, DEF_EMPTY_ADDR, &var_empty_addr, 1, 0,
|
||||
0,
|
||||
};
|
||||
|
||||
single_server_main(argc, argv, showq_service,
|
||||
MAIL_SERVER_INT_TABLE, int_table,
|
||||
MAIL_SERVER_STR_TABLE, str_table,
|
||||
0);
|
||||
}
|
||||
|
|
|
@ -166,6 +166,7 @@ smtp_proto.o: ../../include/rec_type.h
|
|||
smtp_proto.o: ../../include/off_cvt.h
|
||||
smtp_proto.o: ../../include/mark_corrupt.h
|
||||
smtp_proto.o: ../../include/quote_821_local.h
|
||||
smtp_proto.o: ../../include/quote_flags.h
|
||||
smtp_proto.o: smtp.h
|
||||
smtp_proto.o: ../../include/argv.h
|
||||
smtp_proto.o: smtp_sasl.h
|
||||
|
|
|
@ -97,8 +97,8 @@
|
|||
/* Never send EHLO at the start of a connection.
|
||||
/* .IP \fBsmtp_bind_address\fR
|
||||
/* Numerical source network address to bind to when making a connection.
|
||||
/* .IP \fBsmtp_break_lines\fR
|
||||
/* Break lines > \fB$line_length_limit\fR into multiple shorter lines.
|
||||
/* .IP \fBsmtp_line_length_limit\fR
|
||||
/* Length limit for SMTP message content lines. Zero means no limit.
|
||||
/* Some SMTP servers misbehave on long lines.
|
||||
/* .IP \fBsmtp_skip_4xx_greeting\fR
|
||||
/* Skip servers that greet us with a 4xx status code.
|
||||
|
@ -113,7 +113,7 @@
|
|||
/* The time a message must be queued before the CISCO PIX firewall
|
||||
/* <CR><LF>.<CR><LF> bug workaround is turned on.
|
||||
/* .SH "Authentication controls"
|
||||
/* .IP \fBsmtp_enable_sasl_auth\fR
|
||||
/* .IP \fBsmtp_sasl_auth_enable\fR
|
||||
/* Enable per-session authentication as per RFC 2554 (SASL).
|
||||
/* By default, Postfix is built without SASL support.
|
||||
/* .IP \fBsmtp_sasl_password_maps\fR
|
||||
|
@ -259,9 +259,9 @@ char *var_smtp_sasl_passwd;
|
|||
bool var_smtp_sasl_enable;
|
||||
char *var_smtp_bind_addr;
|
||||
bool var_smtp_rand_addr;
|
||||
bool var_smtp_break_lines;
|
||||
int var_smtp_pix_thresh;
|
||||
int var_smtp_pix_delay;
|
||||
int var_smtp_line_limit;
|
||||
|
||||
/*
|
||||
* Global variables. smtp_errno is set by the address lookup routines and by
|
||||
|
@ -429,6 +429,7 @@ int main(int argc, char **argv)
|
|||
0,
|
||||
};
|
||||
static CONFIG_INT_TABLE int_table[] = {
|
||||
VAR_SMTP_LINE_LIMIT, DEF_SMTP_LINE_LIMIT, &var_smtp_line_limit, 0, 0,
|
||||
0,
|
||||
};
|
||||
static CONFIG_BOOL_TABLE bool_table[] = {
|
||||
|
@ -440,7 +441,6 @@ int main(int argc, char **argv)
|
|||
VAR_SMTP_NEVER_EHLO, DEF_SMTP_NEVER_EHLO, &var_smtp_never_ehlo,
|
||||
VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable,
|
||||
VAR_SMTP_RAND_ADDR, DEF_SMTP_RAND_ADDR, &var_smtp_rand_addr,
|
||||
VAR_SMTP_BREAK_LINES, DEF_SMTP_BREAK_LINES, &var_smtp_break_lines,
|
||||
0,
|
||||
};
|
||||
|
||||
|
|
|
@ -296,16 +296,27 @@ int smtp_xfer(SMTP_STATE *state)
|
|||
int sndbuffree;
|
||||
SOCKOPT_SIZE optlen = sizeof(sndbufsize);
|
||||
int mail_from_rejected;
|
||||
int space_left = var_smtp_line_limit;
|
||||
int data_left;
|
||||
char *data_start;
|
||||
|
||||
/*
|
||||
* Macros for readability.
|
||||
*/
|
||||
#define REWRITE_ADDRESS(addr) do { \
|
||||
if (*(addr)) { \
|
||||
quote_821_local(state->scratch, addr); \
|
||||
smtp_unalias_addr(state->scratch2, vstring_str(state->scratch)); \
|
||||
myfree(addr); \
|
||||
addr = mystrdup(vstring_str(state->scratch2)); \
|
||||
#define REWRITE_ADDRESS(dst, mid, src) do { \
|
||||
if (*(src)) { \
|
||||
quote_821_local(mid, src); \
|
||||
smtp_unalias_addr(dst, vstring_str(mid)); \
|
||||
} else { \
|
||||
vstring_strcpy(dst, src); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define QUOTE_ADDRESS(dst, src) do { \
|
||||
if (*(src)) { \
|
||||
quote_821_local(dst, src); \
|
||||
} else { \
|
||||
vstring_strcpy(dst, src); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
@ -396,11 +407,15 @@ int smtp_xfer(SMTP_STATE *state)
|
|||
* Build the MAIL FROM command.
|
||||
*/
|
||||
case SMTP_STATE_MAIL:
|
||||
if (*request->sender)
|
||||
if (var_disable_dns == 0)
|
||||
REWRITE_ADDRESS(request->sender);
|
||||
vstring_sprintf(next_command, "MAIL FROM:<%s>", request->sender);
|
||||
if (state->features & SMTP_FEATURE_SIZE)
|
||||
if (var_disable_dns == 0) {
|
||||
REWRITE_ADDRESS(state->scratch, state->scratch2,
|
||||
request->sender);
|
||||
} else {
|
||||
QUOTE_ADDRESS(state->scratch, request->sender);
|
||||
}
|
||||
vstring_sprintf(next_command, "MAIL FROM:<%s>",
|
||||
vstring_str(state->scratch));
|
||||
if (state->features & SMTP_FEATURE_SIZE) /* RFC 1652 */
|
||||
vstring_sprintf_append(next_command, " SIZE=%lu",
|
||||
request->data_size);
|
||||
next_state = SMTP_STATE_RCPT;
|
||||
|
@ -412,9 +427,14 @@ int smtp_xfer(SMTP_STATE *state)
|
|||
*/
|
||||
case SMTP_STATE_RCPT:
|
||||
rcpt = request->rcpt_list.info + send_rcpt;
|
||||
if (var_disable_dns == 0)
|
||||
REWRITE_ADDRESS(rcpt->address);
|
||||
vstring_sprintf(next_command, "RCPT TO:<%s>", rcpt->address);
|
||||
if (var_disable_dns == 0) {
|
||||
REWRITE_ADDRESS(state->scratch, state->scratch2,
|
||||
rcpt->address);
|
||||
} else {
|
||||
QUOTE_ADDRESS(state->scratch, rcpt->address);
|
||||
}
|
||||
vstring_sprintf(next_command, "RCPT TO:<%s>",
|
||||
vstring_str(state->scratch));
|
||||
if ((next_rcpt = send_rcpt + 1) == request->rcpt_list.len)
|
||||
next_state = SMTP_STATE_DATA;
|
||||
break;
|
||||
|
@ -665,16 +685,38 @@ int smtp_xfer(SMTP_STATE *state)
|
|||
if (prev_type != REC_TYPE_CONT)
|
||||
if (vstring_str(state->scratch)[0] == '.')
|
||||
smtp_fputc('.', session->stream);
|
||||
if (var_smtp_break_lines)
|
||||
rec_type = REC_TYPE_NORM;
|
||||
if (rec_type == REC_TYPE_CONT)
|
||||
smtp_fwrite(vstring_str(state->scratch),
|
||||
VSTRING_LEN(state->scratch),
|
||||
session->stream);
|
||||
else
|
||||
smtp_fputs(vstring_str(state->scratch),
|
||||
VSTRING_LEN(state->scratch),
|
||||
session->stream);
|
||||
|
||||
/*
|
||||
* Deal with an impedance mismatch between Postfix queue
|
||||
* files (record length <= $message_line_length_limit) and
|
||||
* SMTP (DATA record length <= $smtp_line_length_limit). The
|
||||
* code below does a little too much work when the SMTP line
|
||||
* length limit is disabled, but it avoids code duplication,
|
||||
* and thus, it avoids testing and maintenance problems.
|
||||
*/
|
||||
data_left = VSTRING_LEN(state->scratch);
|
||||
data_start = vstring_str(state->scratch);
|
||||
do {
|
||||
if (var_smtp_line_limit > 0 && data_left >= space_left) {
|
||||
smtp_fputs(data_start, space_left, session->stream);
|
||||
data_start += space_left;
|
||||
data_left -= space_left;
|
||||
space_left = var_smtp_line_limit;
|
||||
if (data_left > 0 || rec_type == REC_TYPE_CONT) {
|
||||
smtp_fputc(' ', session->stream);
|
||||
space_left -= 1;
|
||||
}
|
||||
} else {
|
||||
if (rec_type == REC_TYPE_CONT) {
|
||||
smtp_fwrite(data_start, data_left, session->stream);
|
||||
space_left -= data_left;
|
||||
} else {
|
||||
smtp_fputs(data_start, data_left, session->stream);
|
||||
space_left = var_smtp_line_limit;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (data_left > 0);
|
||||
prev_type = rec_type;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ resolve.o: ../../include/rewrite_clnt.h
|
|||
resolve.o: ../../include/resolve_local.h
|
||||
resolve.o: ../../include/mail_conf.h
|
||||
resolve.o: ../../include/quote_822_local.h
|
||||
resolve.o: ../../include/quote_flags.h
|
||||
resolve.o: ../../include/tok822.h
|
||||
resolve.o: ../../include/resolve_clnt.h
|
||||
resolve.o: trivial-rewrite.h
|
||||
|
|
|
@ -97,9 +97,17 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
|
|||
/*
|
||||
* The address is in internalized (unquoted) form, so we must externalize
|
||||
* it first before we can parse it.
|
||||
*
|
||||
* But practically, we have to look at the unquoted form so that routing
|
||||
* characters like @ remain visible, in order to stop user@domain@domain
|
||||
* relay attempts when forwarding mail to a primary Sendmail MX host.
|
||||
*/
|
||||
quote_822_local(addr_buf, addr);
|
||||
tree = tok822_scan_addr(vstring_str(addr_buf));
|
||||
if (var_resolve_dequoted) {
|
||||
tree = tok822_scan_addr(addr);
|
||||
} else {
|
||||
quote_822_local(addr_buf, addr);
|
||||
tree = tok822_scan_addr(vstring_str(addr_buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* Preliminary resolver: strip off all instances of the local domain.
|
||||
|
|
|
@ -118,7 +118,8 @@ void rewrite_tree(char *unused_ruleset, TOK822 *tree)
|
|||
* Strip source route.
|
||||
*/
|
||||
if (tree->head->type == '@'
|
||||
&& (colon = tok822_find_type(tree->head, ':')) != 0)
|
||||
&& (colon = tok822_find_type(tree->head, ':')) != 0
|
||||
&& colon != tree->tail)
|
||||
tok822_free_tree(tok822_sub_keep_after(tree, colon));
|
||||
|
||||
/*
|
||||
|
|
|
@ -64,6 +64,12 @@
|
|||
/* List of domains that this machine considers local.
|
||||
/* .IP \fBmyorigin\fR
|
||||
/* The domain that locally-posted mail appears to come from.
|
||||
/* .IP \fBresolve_unquoted_address\fR
|
||||
/* When resolving an address, do not quote the address localpart as
|
||||
/* per RFC 822, so that additional \fB@\fR, \fB%\fR or \fB!\fR
|
||||
/* characters remain visible. This is technically incorrect, but
|
||||
/* allows us to stop relay attacks when forwarding mail to a Sendmail
|
||||
/* primary MX host.
|
||||
/* .SH Rewriting
|
||||
/* .ad
|
||||
/* .fi
|
||||
|
@ -93,9 +99,9 @@
|
|||
/* Syntax is \fItransport\fR:\fInexthop\fR; see \fBtransport\fR(5)
|
||||
/* for details. The :\fInexthop\fR part is optional.
|
||||
/* .IP \fBparent_domain_matches_subdomains\fR
|
||||
/* List of Postfix features that use \fIdomain.name\fR patterns
|
||||
/* to match \fIsub.domain.name\fR (as opposed to
|
||||
/* requiring \fI.domain.name\fR patterns).
|
||||
/* List of Postfix features that use \fIdomain.tld\fR patterns
|
||||
/* to match \fIsub.domain.tld\fR (as opposed to
|
||||
/* requiring \fI.domain.tld\fR patterns).
|
||||
/* .IP \fBrelayhost\fR
|
||||
/* The default host to send non-local mail to when no entry is matched
|
||||
/* in the \fBtransport\fR(5) table.
|
||||
|
@ -167,6 +173,7 @@ bool var_append_dot_mydomain;
|
|||
bool var_append_at_myorigin;
|
||||
bool var_percent_hack;
|
||||
char *var_local_transport;
|
||||
int var_resolve_dequoted;
|
||||
|
||||
/* rewrite_service - read request and send reply */
|
||||
|
||||
|
@ -234,6 +241,7 @@ int main(int argc, char **argv)
|
|||
VAR_APP_DOT_MYDOMAIN, DEF_APP_DOT_MYDOMAIN, &var_append_dot_mydomain,
|
||||
VAR_APP_AT_MYORIGIN, DEF_APP_AT_MYORIGIN, &var_append_at_myorigin,
|
||||
VAR_PERCENT_HACK, DEF_PERCENT_HACK, &var_percent_hack,
|
||||
VAR_RESOLVE_DEQUOTED, DEF_RESOLVE_DEQUOTED, &var_resolve_dequoted,
|
||||
0,
|
||||
};
|
||||
|
||||
|
|
|
@ -508,11 +508,11 @@ int dict_changed(void)
|
|||
ht_info_list = htable_list(dict_table);
|
||||
for (status = 0, ht = ht_info_list; status == 0 && (h = *ht) != 0; ht++) {
|
||||
dict = ((DICT_NODE *) h->value)->dict;
|
||||
if (dict->fd < 0) /* not file-based */
|
||||
if (dict->stat_fd < 0) /* not file-based */
|
||||
continue;
|
||||
if (dict->mtime == 0) /* not bloody likely */
|
||||
msg_warn("%s: table %s: null time stamp", myname, h->key);
|
||||
if (fstat(dict->fd, &st) < 0)
|
||||
if (fstat(dict->stat_fd, &st) < 0)
|
||||
msg_fatal("%s: fstat: %m", myname);
|
||||
status = (st.st_mtime != dict->mtime || st.st_nlink == 0);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,8 @@ typedef struct DICT {
|
|||
int (*delete) (struct DICT *, const char *);
|
||||
int (*sequence) (struct DICT *, int, const char **, const char **);
|
||||
void (*close) (struct DICT *);
|
||||
int fd; /* for dict_update() lock */
|
||||
int lock_fd; /* for dict_update() lock */
|
||||
int stat_fd; /* change detection */
|
||||
time_t mtime; /* mod time at open */
|
||||
} DICT;
|
||||
|
||||
|
|
|
@ -116,7 +116,8 @@ DICT *dict_alloc(const char *dict_type, const char *dict_name, int size)
|
|||
dict->delete = dict_default_delete;
|
||||
dict->sequence = dict_default_sequence;
|
||||
dict->close = dict_default_close;
|
||||
dict->fd = -1;
|
||||
dict->lock_fd = -1;
|
||||
dict->stat_fd = -1;
|
||||
dict->mtime = 0;
|
||||
return dict;
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
|
|||
* Acquire a shared lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
|
||||
msg_fatal("%s: lock dictionary: %m", dict_db->dict.name);
|
||||
|
||||
/*
|
||||
|
@ -198,7 +198,7 @@ static const char *dict_db_lookup(DICT *dict, const char *name)
|
|||
* Release the shared lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
msg_fatal("%s: unlock dictionary: %m", dict_db->dict.name);
|
||||
|
||||
return (result);
|
||||
|
@ -246,7 +246,7 @@ static void dict_db_update(DICT *dict, const char *name, const char *value)
|
|||
* Acquire an exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
|
||||
msg_fatal("%s: lock dictionary: %m", dict_db->dict.name);
|
||||
|
||||
/*
|
||||
|
@ -271,7 +271,7 @@ static void dict_db_update(DICT *dict, const char *name, const char *value)
|
|||
* Release the exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
msg_fatal("%s: unlock dictionary: %m", dict_db->dict.name);
|
||||
}
|
||||
|
||||
|
@ -289,7 +289,7 @@ static int dict_db_delete(DICT *dict, const char *name)
|
|||
* Acquire an exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
|
||||
msg_fatal("%s: lock dictionary: %m", dict_db->dict.name);
|
||||
|
||||
/*
|
||||
|
@ -325,7 +325,7 @@ static int dict_db_delete(DICT *dict, const char *name)
|
|||
* Release the exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
msg_fatal("%s: unlock dictionary: %m", dict_db->dict.name);
|
||||
|
||||
return status;
|
||||
|
@ -367,7 +367,7 @@ static int dict_db_sequence(DICT *dict, const int function,
|
|||
* Acquire an exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
|
||||
msg_fatal("%s: lock dictionary: %m", dict_db->dict.name);
|
||||
|
||||
if ((status = db->seq(db, &db_key, &db_value, db_function)) < 0)
|
||||
|
@ -377,7 +377,7 @@ static int dict_db_sequence(DICT *dict, const int function,
|
|||
* Release the exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
msg_fatal("%s: unlock dictionary: %m", dict_db->dict.name);
|
||||
|
||||
if (status == 0) {
|
||||
|
@ -537,8 +537,9 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
|
|||
dict_db->dict.delete = dict_db_delete;
|
||||
dict_db->dict.sequence = dict_db_sequence;
|
||||
dict_db->dict.close = dict_db_close;
|
||||
dict_db->dict.fd = dbfd;
|
||||
if (fstat(dict_db->dict.fd, &st) < 0)
|
||||
dict_db->dict.lock_fd = dbfd;
|
||||
dict_db->dict.stat_fd = dbfd;
|
||||
if (fstat(dict_db->dict.stat_fd, &st) < 0)
|
||||
msg_fatal("dict_db_open: fstat: %m");
|
||||
dict_db->dict.mtime = st.st_mtime;
|
||||
|
||||
|
@ -552,7 +553,8 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
|
|||
&& st.st_mtime < time((time_t *) 0) - 100)
|
||||
msg_warn("database %s is older than source file %s", db_path, path);
|
||||
|
||||
close_on_exec(dict_db->dict.fd, CLOSE_ON_EXEC);
|
||||
close_on_exec(dict_db->dict.lock_fd, CLOSE_ON_EXEC);
|
||||
close_on_exec(dict_db->dict.stat_fd, CLOSE_ON_EXEC);
|
||||
dict_db->dict.flags = dict_flags | DICT_FLAG_FIXED;
|
||||
if ((dict_flags & (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL)) == 0)
|
||||
dict_db->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL);
|
||||
|
|
|
@ -84,7 +84,7 @@ static const char *dict_dbm_lookup(DICT *dict, const char *name)
|
|||
* Acquire an exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
|
||||
msg_fatal("%s: lock dictionary: %m", dict_dbm->dict.name);
|
||||
|
||||
/*
|
||||
|
@ -122,7 +122,7 @@ static const char *dict_dbm_lookup(DICT *dict, const char *name)
|
|||
* Release the exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
msg_fatal("%s: unlock dictionary: %m", dict_dbm->dict.name);
|
||||
|
||||
return (result);
|
||||
|
@ -167,7 +167,7 @@ static void dict_dbm_update(DICT *dict, const char *name, const char *value)
|
|||
* Acquire an exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
|
||||
msg_fatal("%s: lock dictionary: %m", dict_dbm->dict.name);
|
||||
|
||||
/*
|
||||
|
@ -189,7 +189,7 @@ static void dict_dbm_update(DICT *dict, const char *name, const char *value)
|
|||
* Release the exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
msg_fatal("%s: unlock dictionary: %m", dict_dbm->dict.name);
|
||||
}
|
||||
|
||||
|
@ -206,7 +206,7 @@ static int dict_dbm_delete(DICT *dict, const char *name)
|
|||
* Acquire an exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
|
||||
msg_fatal("%s: lock dictionary: %m", dict_dbm->dict.name);
|
||||
|
||||
/*
|
||||
|
@ -247,7 +247,7 @@ static int dict_dbm_delete(DICT *dict, const char *name)
|
|||
* Release the exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
msg_fatal("%s: unlock dictionary: %m", dict_dbm->dict.name);
|
||||
|
||||
return (status);
|
||||
|
@ -270,7 +270,7 @@ static int dict_dbm_sequence(DICT *dict, const int function,
|
|||
* Acquire an exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
|
||||
msg_fatal("%s: lock dictionary: %m", dict_dbm->dict.name);
|
||||
|
||||
/*
|
||||
|
@ -291,7 +291,7 @@ static int dict_dbm_sequence(DICT *dict, const int function,
|
|||
* Release the exclusive lock.
|
||||
*/
|
||||
if ((dict->flags & DICT_FLAG_LOCK)
|
||||
&& myflock(dict->fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
&& myflock(dict->lock_fd, INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
|
||||
msg_fatal("%s: unlock dictionary: %m", dict_dbm->dict.name);
|
||||
|
||||
if (dbm_key.dptr != 0 && dbm_key.dsize > 0) {
|
||||
|
@ -379,7 +379,7 @@ DICT *dict_dbm_open(const char *path, int open_flags, int dict_flags)
|
|||
* time domain) locks while rewriting the entire file.
|
||||
*/
|
||||
if (dict_flags & DICT_FLAG_LOCK) {
|
||||
dbm_path = concatenate(path, ".pag", (char *) 0);
|
||||
dbm_path = concatenate(path, ".dir", (char *) 0);
|
||||
if ((lock_fd = open(dbm_path, open_flags, 0644)) < 0)
|
||||
msg_fatal("open database %s: %m", dbm_path);
|
||||
if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
|
||||
|
@ -404,8 +404,11 @@ DICT *dict_dbm_open(const char *path, int open_flags, int dict_flags)
|
|||
dict_dbm->dict.delete = dict_dbm_delete;
|
||||
dict_dbm->dict.sequence = dict_dbm_sequence;
|
||||
dict_dbm->dict.close = dict_dbm_close;
|
||||
dict_dbm->dict.fd = dbm_pagfno(dbm);
|
||||
if (fstat(dict_dbm->dict.fd, &st) < 0)
|
||||
dict_dbm->dict.lock_fd = dbm_dirfno(dbm);
|
||||
dict_dbm->dict.stat_fd = dbm_pagfno(dbm);
|
||||
if (dict_dbm->dict.lock_fd == dict_dbm->dict.stat_fd)
|
||||
msg_fatal("open database %s: cannot support GDBM", path);
|
||||
if (fstat(dict_dbm->dict.stat_fd, &st) < 0)
|
||||
msg_fatal("dict_dbm_open: fstat: %m");
|
||||
dict_dbm->dict.mtime = st.st_mtime;
|
||||
|
||||
|
|
|
@ -586,7 +586,7 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name)
|
|||
*/
|
||||
if (*(sub) == '%') {
|
||||
char *u = vstring_str(escaped_name);
|
||||
char *p = strchr(u, '@');
|
||||
char *p = strrchr(u, '@');
|
||||
|
||||
switch (*(sub + 1)) {
|
||||
case 'd':
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 1987, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <ctype.h>
|
||||
|
||||
int strcasecmp(const char *s1, const char *s2)
|
||||
{
|
||||
const unsigned char *us1 = (const unsigned char *) s1;
|
||||
const unsigned char *us2 = (const unsigned char *) s2;
|
||||
|
||||
while (TOLOWER(*us1) == TOLOWER(*us2++))
|
||||
if (*us1++ == '\0')
|
||||
return (0);
|
||||
return (TOLOWER(*us1) - TOLOWER(*--us2));
|
||||
}
|
||||
|
||||
int strncasecmp(const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
if (n != 0) {
|
||||
const unsigned char *us1 = (const unsigned char *) s1;
|
||||
const unsigned char *us2 = (const unsigned char *) s2;
|
||||
|
||||
do {
|
||||
if (TOLOWER(*us1) != TOLOWER(*us2++))
|
||||
return (TOLOWER(*us1) - TOLOWER(*--us2));
|
||||
if (*us1++ == '\0')
|
||||
break;
|
||||
} while (--n != 0);
|
||||
}
|
||||
return (0);
|
||||
}
|
Loading…
Reference in New Issue