mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-31 14:17:41 +00:00
postfix-2.5.12
This commit is contained in:
committed by
Viktor Dukhovni
parent
b3ab42ccc0
commit
f6a26a3518
@@ -14571,6 +14571,18 @@ Apologies for any names omitted.
|
|||||||
2821 (and 5321) is vague about the VRFY request format, but
|
2821 (and 5321) is vague about the VRFY request format, but
|
||||||
spends lots of text on the reply format. File: smtpd/smtpd.c.
|
spends lots of text on the reply format. File: smtpd/smtpd.c.
|
||||||
|
|
||||||
|
20100422
|
||||||
|
|
||||||
|
Workaround (introduced: postfix-19990906 a.k.a. Postfix
|
||||||
|
0.8.0). The Postfix local delivery agent did not properly
|
||||||
|
distinguish between "address has no extension" and "address
|
||||||
|
has an extension, but the extension is invalid". In both
|
||||||
|
cases it would run only the full recipient local-part through
|
||||||
|
the alias maps. Instead, it now drops the faulty extension
|
||||||
|
from the recipient address local-part (it would be too
|
||||||
|
error-prone to replace all tests for "no extension" by tests
|
||||||
|
for "no valid extension". File: local/recipient.c.
|
||||||
|
|
||||||
20100610
|
20100610
|
||||||
|
|
||||||
Bugfix (introduced Postfix 2.2): Postfix no longer appends
|
Bugfix (introduced Postfix 2.2): Postfix no longer appends
|
||||||
@@ -14610,3 +14622,59 @@ Apologies for any names omitted.
|
|||||||
compliance. We now make an exception for "final" replies,
|
compliance. We now make an exception for "final" replies,
|
||||||
as permitted by RFC. Solution by Victor Duchovni. File:
|
as permitted by RFC. Solution by Victor Duchovni. File:
|
||||||
smtpd/smtpd.c.
|
smtpd/smtpd.c.
|
||||||
|
|
||||||
|
20101201
|
||||||
|
|
||||||
|
Workaround: BSD-ish mkdir() ignores the effective GID and
|
||||||
|
copies group ownership from the parent directory. File:
|
||||||
|
util/make_dirs.c.
|
||||||
|
|
||||||
|
20101202
|
||||||
|
|
||||||
|
Cleanup: the cleanup server now reports a temporary delivery
|
||||||
|
error when it reaches the virtual_alias_expansion_limit or
|
||||||
|
virtual_alias_recursion_limit. Previously, it would silently
|
||||||
|
ignore the excess recipients and deliver the message. File:
|
||||||
|
cleanup/cleanup_map1n.c.
|
||||||
|
|
||||||
|
20110105
|
||||||
|
|
||||||
|
Bugfix (introduced with the Postfix TLS patch): discard
|
||||||
|
plaintext following the STARTTLS command or response. This
|
||||||
|
matters only for the minority of SMTP clients that actually
|
||||||
|
verify server certificates. Files: smtpd/smtpd.c,
|
||||||
|
smtp/smtp_proto.c.
|
||||||
|
|
||||||
|
This vulnerability is also known as CVE-2011-0411.
|
||||||
|
|
||||||
|
20110109
|
||||||
|
|
||||||
|
Bugfix (introduced Postfix 2.4): on Solaris the Postfix
|
||||||
|
event engine was deaf for SIGHUP and SIGALRM signals after
|
||||||
|
the switch to /dev/poll. Symptoms were delayed "postfix
|
||||||
|
reload" response, and killed processes when the watchdog
|
||||||
|
timeout was less than max_idle. The fix is to set up SIGHUP
|
||||||
|
and SIGALRM handlers that write to a pipe, and to monitor
|
||||||
|
that pipe for read events via the Postfix event engine.
|
||||||
|
Files: master/master_sig.c, util/watchdog.c, util/sys_defs.h.
|
||||||
|
|
||||||
|
20110117
|
||||||
|
|
||||||
|
Bugfix (introduced Postfix alpha, or thereabouts): on HP-UX
|
||||||
|
the Postfix event engine was deaf for SIGALRM signals.
|
||||||
|
Symptoms were killed processes when the watchdog timeout
|
||||||
|
was less than max_idle. The fix is the same as Solaris fix
|
||||||
|
20110109. Since we can't know what other systems need this,
|
||||||
|
the workaround is enabled by default. Files: util/sys_defs.h.
|
||||||
|
|
||||||
|
20110225
|
||||||
|
|
||||||
|
Workaround (problem introduced with IPv6 support in Postfix
|
||||||
|
2.2): the SMTP client did not support mail to [ipv6:ipv6addr].
|
||||||
|
Fix based on a patch by Gurusamy Sarathy (Sophos). File:
|
||||||
|
util/host_port.c and regression test files.
|
||||||
|
|
||||||
|
20110227
|
||||||
|
|
||||||
|
Portability: FreeBSD closefrom() support time window. Sahil
|
||||||
|
Tandon. File: util/sys_defs.h.
|
||||||
|
@@ -214,6 +214,12 @@ case "$SYSTEM.$RELEASE" in
|
|||||||
done
|
done
|
||||||
;;
|
;;
|
||||||
AIX.*) case "`uname -v`" in
|
AIX.*) case "`uname -v`" in
|
||||||
|
6) SYSTYPE=AIX6
|
||||||
|
case "$CC" in
|
||||||
|
cc|*/cc|xlc|*/xlc) CCARGS="$CCARGS -w -blibpath:/usr/lib:/lib:/usr/local/lib";;
|
||||||
|
esac
|
||||||
|
CCARGS="$CCARGS -D_ALL_SOURCE -DHAS_POSIX_REGEXP"
|
||||||
|
;;
|
||||||
5) SYSTYPE=AIX5
|
5) SYSTYPE=AIX5
|
||||||
case "$CC" in
|
case "$CC" in
|
||||||
cc|*/cc|xlc|*/xlc) CCARGS="$CCARGS -w -blibpath:/usr/lib:/lib:/usr/local/lib";;
|
cc|*/cc|xlc|*/xlc) CCARGS="$CCARGS -w -blibpath:/usr/lib:/lib:/usr/local/lib";;
|
||||||
|
@@ -15,13 +15,18 @@
|
|||||||
/* This module implements one-to-many table mapping via table lookup.
|
/* This module implements one-to-many table mapping via table lookup.
|
||||||
/* Table lookups are done with quoted (externalized) address forms.
|
/* Table lookups are done with quoted (externalized) address forms.
|
||||||
/* The process is recursive. The recursion terminates when the
|
/* The process is recursive. The recursion terminates when the
|
||||||
/* left-hand side appears in its own expansion, or when a maximal
|
/* left-hand side appears in its own expansion.
|
||||||
/* nesting level is reached.
|
|
||||||
/*
|
/*
|
||||||
/* cleanup_map1n_internal() is the interface for addresses in
|
/* cleanup_map1n_internal() is the interface for addresses in
|
||||||
/* internal (unquoted) form.
|
/* internal (unquoted) form.
|
||||||
/* DIAGNOSTICS
|
/* DIAGNOSTICS
|
||||||
/* Recoverable errors: the global \fIcleanup_errs\fR flag is updated.
|
/* When the maximal expansion or recursion limit is reached,
|
||||||
|
/* the alias is not expanded and the CLEANUP_STAT_DEFER error
|
||||||
|
/* is raised with reason "4.6.0 Alias expansion error".
|
||||||
|
/*
|
||||||
|
/* When table lookup fails, the alias is not expanded and the
|
||||||
|
/* CLEANUP_STAT_WRITE error is raised with reason "4.6.0 Alias
|
||||||
|
/* expansion error".
|
||||||
/* SEE ALSO
|
/* SEE ALSO
|
||||||
/* mail_addr_map(3) address mappings
|
/* mail_addr_map(3) address mappings
|
||||||
/* mail_addr_find(3) address lookups
|
/* mail_addr_find(3) address lookups
|
||||||
@@ -93,15 +98,26 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr,
|
|||||||
* must index the array explicitly, instead of running along it with a
|
* must index the array explicitly, instead of running along it with a
|
||||||
* pointer.
|
* pointer.
|
||||||
*/
|
*/
|
||||||
#define UPDATE(ptr,new) { myfree(ptr); ptr = mystrdup(new); }
|
#define UPDATE(ptr,new) do { \
|
||||||
|
if (ptr) myfree(ptr); ptr = mystrdup(new); \
|
||||||
|
} while (0)
|
||||||
#define STR vstring_str
|
#define STR vstring_str
|
||||||
#define RETURN(x) { been_here_free(been_here); return (x); }
|
#define RETURN(x) do { \
|
||||||
|
been_here_free(been_here); return (x); \
|
||||||
|
} while (0)
|
||||||
|
#define UNEXPAND(argv, addr) do { \
|
||||||
|
argv_truncate((argv), 0); argv_add((argv), (addr), (char *) 0); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
for (arg = 0; arg < argv->argc; arg++) {
|
for (arg = 0; arg < argv->argc; arg++) {
|
||||||
if (argv->argc > var_virt_expan_limit) {
|
if (argv->argc > var_virt_expan_limit) {
|
||||||
msg_warn("%s: unreasonable %s map expansion size for %s",
|
msg_warn("%s: unreasonable %s map expansion size for %s -- "
|
||||||
|
"deferring delivery",
|
||||||
state->queue_id, maps->title, addr);
|
state->queue_id, maps->title, addr);
|
||||||
break;
|
state->errs |= CLEANUP_STAT_DEFER;
|
||||||
|
UPDATE(state->reason, "4.6.0 Alias expansion error");
|
||||||
|
UNEXPAND(argv, addr);
|
||||||
|
RETURN(argv);
|
||||||
}
|
}
|
||||||
for (count = 0; /* void */ ; count++) {
|
for (count = 0; /* void */ ; count++) {
|
||||||
|
|
||||||
@@ -111,9 +127,13 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr,
|
|||||||
if (been_here_check_fixed(been_here, argv->argv[arg]) != 0)
|
if (been_here_check_fixed(been_here, argv->argv[arg]) != 0)
|
||||||
break;
|
break;
|
||||||
if (count >= var_virt_recur_limit) {
|
if (count >= var_virt_recur_limit) {
|
||||||
msg_warn("%s: unreasonable %s map nesting for %s",
|
msg_warn("%s: unreasonable %s map nesting for %s -- "
|
||||||
|
"deferring delivery",
|
||||||
state->queue_id, maps->title, addr);
|
state->queue_id, maps->title, addr);
|
||||||
break;
|
state->errs |= CLEANUP_STAT_DEFER;
|
||||||
|
UPDATE(state->reason, "4.6.0 Alias expansion error");
|
||||||
|
UNEXPAND(argv, addr);
|
||||||
|
RETURN(argv);
|
||||||
}
|
}
|
||||||
quote_822_local(state->temp1, argv->argv[arg]);
|
quote_822_local(state->temp1, argv->argv[arg]);
|
||||||
if ((lookup = mail_addr_map(maps, STR(state->temp1), propagate)) != 0) {
|
if ((lookup = mail_addr_map(maps, STR(state->temp1), propagate)) != 0) {
|
||||||
@@ -136,9 +156,12 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr,
|
|||||||
myfree(saved_lhs);
|
myfree(saved_lhs);
|
||||||
argv_free(lookup);
|
argv_free(lookup);
|
||||||
} else if (dict_errno != 0) {
|
} else if (dict_errno != 0) {
|
||||||
msg_warn("%s: %s map lookup problem for %s",
|
msg_warn("%s: %s map lookup problem for %s -- "
|
||||||
|
"deferring delivery",
|
||||||
state->queue_id, maps->title, addr);
|
state->queue_id, maps->title, addr);
|
||||||
state->errs |= CLEANUP_STAT_WRITE;
|
state->errs |= CLEANUP_STAT_WRITE;
|
||||||
|
UPDATE(state->reason, "4.6.0 Alias expansion error");
|
||||||
|
UNEXPAND(argv, addr);
|
||||||
RETURN(argv);
|
RETURN(argv);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@@ -20,8 +20,8 @@
|
|||||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||||
* patchlevel; they change the release date only.
|
* patchlevel; they change the release date only.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20101123"
|
#define MAIL_RELEASE_DATE "20110303"
|
||||||
#define MAIL_VERSION_NUMBER "2.5.11"
|
#define MAIL_VERSION_NUMBER "2.5.12"
|
||||||
|
|
||||||
#ifdef SNAPSHOT
|
#ifdef SNAPSHOT
|
||||||
# define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE
|
# define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE
|
||||||
|
@@ -287,6 +287,10 @@ int deliver_recipient(LOCAL_STATE state, USER_ATTR usr_attr)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Address extension management.
|
* Address extension management.
|
||||||
|
*
|
||||||
|
* XXX Fix 20100422, finalized 20100529: it is too error-prone to
|
||||||
|
* distinguish between "no extension" and "no valid extension", so we
|
||||||
|
* drop an invalid extension from the recipient address local-part.
|
||||||
*/
|
*/
|
||||||
state.msg_attr.user = mystrdup(state.msg_attr.local);
|
state.msg_attr.user = mystrdup(state.msg_attr.local);
|
||||||
if (*var_rcpt_delim) {
|
if (*var_rcpt_delim) {
|
||||||
@@ -296,6 +300,9 @@ int deliver_recipient(LOCAL_STATE state, USER_ATTR usr_attr)
|
|||||||
msg_warn("%s: address with illegal extension: %s",
|
msg_warn("%s: address with illegal extension: %s",
|
||||||
state.msg_attr.queue_id, state.msg_attr.local);
|
state.msg_attr.queue_id, state.msg_attr.local);
|
||||||
state.msg_attr.extension = 0;
|
state.msg_attr.extension = 0;
|
||||||
|
/* XXX Can't myfree + mystrdup, must truncate instead. */
|
||||||
|
state.msg_attr.local[strlen(state.msg_attr.user)] = 0;
|
||||||
|
/* Truncating is safe. The code below rejects null usernames. */
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
state.msg_attr.extension = 0;
|
state.msg_attr.extension = 0;
|
||||||
|
@@ -53,9 +53,8 @@
|
|||||||
|
|
||||||
#ifdef USE_SIG_RETURN
|
#ifdef USE_SIG_RETURN
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#endif
|
#undef USE_SIG_PIPE
|
||||||
|
#else
|
||||||
#ifndef USE_SIG_RETURN
|
|
||||||
#define USE_SIG_PIPE
|
#define USE_SIG_PIPE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -76,6 +75,8 @@ int master_sig_pipe[2];
|
|||||||
int master_gotsigchld;
|
int master_gotsigchld;
|
||||||
int master_gotsighup;
|
int master_gotsighup;
|
||||||
|
|
||||||
|
#ifdef USE_SIG_RETURN
|
||||||
|
|
||||||
/* master_sighup - register arrival of hangup signal */
|
/* master_sighup - register arrival of hangup signal */
|
||||||
|
|
||||||
static void master_sighup(int sig)
|
static void master_sighup(int sig)
|
||||||
@@ -92,8 +93,6 @@ static void master_sighup(int sig)
|
|||||||
|
|
||||||
/* master_sigchld - register arrival of child death signal */
|
/* master_sigchld - register arrival of child death signal */
|
||||||
|
|
||||||
#ifdef USE_SIG_RETURN
|
|
||||||
|
|
||||||
static void master_sigchld(int sig, int code, struct sigcontext * scp)
|
static void master_sigchld(int sig, int code, struct sigcontext * scp)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -116,7 +115,25 @@ static void master_sigchld(int sig, int code, struct sigcontext * scp)
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifdef USE_SIG_PIPE
|
/* master_sighup - register arrival of hangup signal */
|
||||||
|
|
||||||
|
static void master_sighup(int sig)
|
||||||
|
{
|
||||||
|
int saved_errno = errno;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WARNING WARNING WARNING.
|
||||||
|
*
|
||||||
|
* This code runs at unpredictable moments, as a signal handler. Don't put
|
||||||
|
* any code here other than for setting a global flag, or code that is
|
||||||
|
* intended to be run within a signal handler. Restore errno in case we
|
||||||
|
* are interrupting the epilog of a failed system call.
|
||||||
|
*/
|
||||||
|
master_gotsighup = sig;
|
||||||
|
if (write(SIG_PIPE_WRITE_FD, "", 1) != 1)
|
||||||
|
msg_warn("write to SIG_PIPE_WRITE_FD failed: %m");
|
||||||
|
errno = saved_errno;
|
||||||
|
}
|
||||||
|
|
||||||
/* master_sigchld - force wakeup from select() */
|
/* master_sigchld - force wakeup from select() */
|
||||||
|
|
||||||
@@ -132,6 +149,7 @@ static void master_sigchld(int unused_sig)
|
|||||||
* intended to be run within a signal handler. Restore errno in case we
|
* intended to be run within a signal handler. Restore errno in case we
|
||||||
* are interrupting the epilog of a failed system call.
|
* are interrupting the epilog of a failed system call.
|
||||||
*/
|
*/
|
||||||
|
master_gotsigchld = 1;
|
||||||
if (write(SIG_PIPE_WRITE_FD, "", 1) != 1)
|
if (write(SIG_PIPE_WRITE_FD, "", 1) != 1)
|
||||||
msg_warn("write to SIG_PIPE_WRITE_FD failed: %m");
|
msg_warn("write to SIG_PIPE_WRITE_FD failed: %m");
|
||||||
errno = saved_errno;
|
errno = saved_errno;
|
||||||
@@ -145,24 +163,8 @@ static void master_sig_event(int unused_event, char *unused_context)
|
|||||||
|
|
||||||
while (read(SIG_PIPE_READ_FD, c, 1) > 0)
|
while (read(SIG_PIPE_READ_FD, c, 1) > 0)
|
||||||
/* void */ ;
|
/* void */ ;
|
||||||
master_gotsigchld = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
static void master_sigchld(int sig)
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* WARNING WARNING WARNING.
|
|
||||||
*
|
|
||||||
* This code runs at unpredictable moments, as a signal handler. Don't put
|
|
||||||
* any code here other than for setting a global flag.
|
|
||||||
*/
|
|
||||||
master_gotsigchld = sig;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* master_sigdeath - die, women and children first */
|
/* master_sigdeath - die, women and children first */
|
||||||
|
@@ -811,6 +811,9 @@ static int smtp_start_tls(SMTP_STATE *state)
|
|||||||
SMTP_RESP_FAKE(&fake, "4.7.5"),
|
SMTP_RESP_FAKE(&fake, "4.7.5"),
|
||||||
"Server certificate not verified"));
|
"Server certificate not verified"));
|
||||||
|
|
||||||
|
/* At this point there must not be any pending plaintext. */
|
||||||
|
vstream_fpurge(session->stream, VSTREAM_PURGE_BOTH);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this point we have to re-negotiate the "EHLO" to reget the
|
* At this point we have to re-negotiate the "EHLO" to reget the
|
||||||
* feature-list.
|
* feature-list.
|
||||||
|
@@ -3911,6 +3911,8 @@ static int starttls_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
|||||||
smtpd_chat_reply(state, "220 2.0.0 Ready to start TLS");
|
smtpd_chat_reply(state, "220 2.0.0 Ready to start TLS");
|
||||||
/* Flush before we switch the stream's read/write routines. */
|
/* Flush before we switch the stream's read/write routines. */
|
||||||
smtp_flush(state->client);
|
smtp_flush(state->client);
|
||||||
|
/* At this point there must not be any pending plaintext. */
|
||||||
|
vstream_fpurge(state->client, VSTREAM_PURGE_BOTH);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset all inputs to the initial state.
|
* Reset all inputs to the initial state.
|
||||||
|
@@ -95,22 +95,41 @@
|
|||||||
|
|
||||||
#include <host_port.h>
|
#include <host_port.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Point-fix workaround. The libutil library should be email agnostic, but
|
||||||
|
* we can't rip up the library APIs in the stable releases.
|
||||||
|
*/
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef STRCASECMP_IN_STRINGS_H
|
||||||
|
#include <strings.h>
|
||||||
|
#endif
|
||||||
|
#define IPV6_COL "IPv6:" /* RFC 2821 */
|
||||||
|
#define IPV6_COL_LEN (sizeof(IPV6_COL) - 1)
|
||||||
|
#define HAS_IPV6_COL(str) (strncasecmp((str), IPV6_COL, IPV6_COL_LEN) == 0)
|
||||||
|
|
||||||
/* host_port - parse string into host and port, destroy string */
|
/* host_port - parse string into host and port, destroy string */
|
||||||
|
|
||||||
const char *host_port(char *buf, char **host, char *def_host,
|
const char *host_port(char *buf, char **host, char *def_host,
|
||||||
char **port, char *def_service)
|
char **port, char *def_service)
|
||||||
{
|
{
|
||||||
char *cp = buf;
|
char *cp = buf;
|
||||||
|
int ipv6 = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* [host]:port, [host]:, [host].
|
* [host]:port, [host]:, [host].
|
||||||
|
* [ipv6:ipv6addr]:port, [ipv6:ipv6addr]:, [ipv6:ipv6addr].
|
||||||
*/
|
*/
|
||||||
if (*cp == '[') {
|
if (*cp == '[') {
|
||||||
*host = ++cp;
|
++cp;
|
||||||
|
if ((ipv6 = HAS_IPV6_COL(cp)) != 0)
|
||||||
|
cp += IPV6_COL_LEN;
|
||||||
|
*host = cp;
|
||||||
if ((cp = split_at(cp, ']')) == 0)
|
if ((cp = split_at(cp, ']')) == 0)
|
||||||
return ("missing \"]\"");
|
return ("missing \"]\"");
|
||||||
if (*cp && *cp++ != ':')
|
if (*cp && *cp++ != ':')
|
||||||
return ("garbage after \"]\"");
|
return ("garbage after \"]\"");
|
||||||
|
if (ipv6 && !valid_ipv6_hostaddr(*host, DONT_GRIPE))
|
||||||
|
return ("malformed IPv6 address");
|
||||||
*port = *cp ? cp : def_service;
|
*port = *cp ? cp : def_service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
/* Utility library. */
|
/* Utility library. */
|
||||||
|
|
||||||
@@ -49,12 +50,14 @@
|
|||||||
|
|
||||||
int make_dirs(const char *path, int perms)
|
int make_dirs(const char *path, int perms)
|
||||||
{
|
{
|
||||||
|
const char *myname = "make_dirs";
|
||||||
char *saved_path;
|
char *saved_path;
|
||||||
unsigned char *cp;
|
unsigned char *cp;
|
||||||
int saved_ch;
|
int saved_ch;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int ret;
|
int ret;
|
||||||
mode_t saved_mode = 0;
|
mode_t saved_mode = 0;
|
||||||
|
gid_t egid = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize. Make a copy of the path that we can safely clobber.
|
* Initialize. Make a copy of the path that we can safely clobber.
|
||||||
@@ -117,6 +120,21 @@ int make_dirs(const char *path, int perms)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fix directory ownership when mkdir() ignores the effective
|
||||||
|
* GID. Don't change the effective UID for doing this.
|
||||||
|
*/
|
||||||
|
if ((ret = stat(saved_path, &st)) < 0) {
|
||||||
|
msg_warn("%s: stat %s: %m", myname, saved_path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (egid == -1)
|
||||||
|
egid = getegid();
|
||||||
|
if (st.st_gid != egid && (ret = chown(saved_path, -1, egid)) < 0) {
|
||||||
|
msg_warn("%s: chgrp %s: %m", myname, saved_path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (saved_ch != 0)
|
if (saved_ch != 0)
|
||||||
*cp = saved_ch;
|
*cp = saved_ch;
|
||||||
|
@@ -111,7 +111,8 @@
|
|||||||
#define HAS_DUPLEX_PIPE /* 4.1 breaks with kqueue(2) */
|
#define HAS_DUPLEX_PIPE /* 4.1 breaks with kqueue(2) */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __FreeBSD_version >= 800098 /* commit: r194262 */
|
#if (__FreeBSD_version >= 702104 && __FreeBSD_version <= 800000) \
|
||||||
|
|| __FreeBSD_version >= 800100
|
||||||
#define HAS_CLOSEFROM
|
#define HAS_CLOSEFROM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -506,7 +507,7 @@ extern int opterr;
|
|||||||
* AIX: a SYSV-flavored hybrid. NB: fcntl() and flock() access the same
|
* AIX: a SYSV-flavored hybrid. NB: fcntl() and flock() access the same
|
||||||
* underlying locking primitives.
|
* underlying locking primitives.
|
||||||
*/
|
*/
|
||||||
#ifdef AIX5
|
#if defined(AIX5) || defined(AIX6)
|
||||||
#define SUPPORTED
|
#define SUPPORTED
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#define UINT32_TYPE unsigned int
|
#define UINT32_TYPE unsigned int
|
||||||
@@ -1261,6 +1262,17 @@ extern int dup2_pass_on_exec(int oldd, int newd);
|
|||||||
extern const char *inet_ntop(int, const void *, char *, size_t);
|
extern const char *inet_ntop(int, const void *, char *, size_t);
|
||||||
extern int inet_pton(int, const char *, void *);
|
extern int inet_pton(int, const char *, void *);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workaround: after a watchdog alarm signal, wake up from select/poll/etc.
|
||||||
|
* by writing to a pipe. Solaris needs this, and HP-UX apparently, too. The
|
||||||
|
* run-time cost is negligible so we just turn it on for all systems. As a
|
||||||
|
* side benefit, making this code system-independent will simplify the
|
||||||
|
* detection of bit-rot problems.
|
||||||
|
*/
|
||||||
|
#ifndef NO_WATCHDOG_PIPE
|
||||||
|
#define USE_WATCHDOG_PIPE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -119,6 +119,31 @@ struct WATCHDOG {
|
|||||||
*/
|
*/
|
||||||
static WATCHDOG *watchdog_curr;
|
static WATCHDOG *watchdog_curr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Workaround for systems where the alarm signal does not wakeup the event
|
||||||
|
* machinery, and therefore does not restart the watchdog timer in the
|
||||||
|
* single_server etc. skeletons. The symptom is that programs abort when the
|
||||||
|
* watchdog timeout is less than the max_idle time.
|
||||||
|
*/
|
||||||
|
#ifdef USE_WATCHDOG_PIPE
|
||||||
|
#include <errno.h>
|
||||||
|
#include <iostuff.h>
|
||||||
|
#include <events.h>
|
||||||
|
|
||||||
|
static int watchdog_pipe[2];
|
||||||
|
|
||||||
|
/* watchdog_read - read event pipe */
|
||||||
|
|
||||||
|
static void watchdog_read(int unused_event, char *unused_context)
|
||||||
|
{
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
while (read(watchdog_pipe[0], &ch, 1) > 0)
|
||||||
|
/* void */ ;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_WATCHDOG_PIPE */
|
||||||
|
|
||||||
/* watchdog_event - handle timeout event */
|
/* watchdog_event - handle timeout event */
|
||||||
|
|
||||||
static void watchdog_event(int unused_sig)
|
static void watchdog_event(int unused_sig)
|
||||||
@@ -137,6 +162,14 @@ static void watchdog_event(int unused_sig)
|
|||||||
if (msg_verbose > 1)
|
if (msg_verbose > 1)
|
||||||
msg_info("%s: %p %d", myname, (void *) wp, wp->trip_run);
|
msg_info("%s: %p %d", myname, (void *) wp, wp->trip_run);
|
||||||
if (++(wp->trip_run) < WATCHDOG_STEPS) {
|
if (++(wp->trip_run) < WATCHDOG_STEPS) {
|
||||||
|
#ifdef USE_WATCHDOG_PIPE
|
||||||
|
int saved_errno = errno;
|
||||||
|
|
||||||
|
/* Wake up the events(3) engine. */
|
||||||
|
if (write(watchdog_pipe[1], "", 1) != 1)
|
||||||
|
msg_warn("%s: write watchdog_pipe: %m", myname);
|
||||||
|
errno = saved_errno;
|
||||||
|
#endif
|
||||||
alarm(wp->timeout);
|
alarm(wp->timeout);
|
||||||
} else {
|
} else {
|
||||||
if (wp->action)
|
if (wp->action)
|
||||||
@@ -177,6 +210,15 @@ WATCHDOG *watchdog_create(unsigned timeout, WATCHDOG_FN action, char *context)
|
|||||||
msg_fatal("%s: sigaction(SIGALRM): %m", myname);
|
msg_fatal("%s: sigaction(SIGALRM): %m", myname);
|
||||||
if (msg_verbose > 1)
|
if (msg_verbose > 1)
|
||||||
msg_info("%s: %p %d", myname, (void *) wp, timeout);
|
msg_info("%s: %p %d", myname, (void *) wp, timeout);
|
||||||
|
#ifdef USE_WATCHDOG_PIPE
|
||||||
|
if (watchdog_curr == 0) {
|
||||||
|
if (pipe(watchdog_pipe) < 0)
|
||||||
|
msg_fatal("%s: pipe: %m", myname);
|
||||||
|
non_blocking(watchdog_pipe[0], NON_BLOCKING);
|
||||||
|
non_blocking(watchdog_pipe[1], NON_BLOCKING);
|
||||||
|
event_enable_read(watchdog_pipe[0], watchdog_read, (char *) 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return (watchdog_curr = wp);
|
return (watchdog_curr = wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,6 +235,13 @@ void watchdog_destroy(WATCHDOG *wp)
|
|||||||
if (wp->saved_time)
|
if (wp->saved_time)
|
||||||
alarm(wp->saved_time);
|
alarm(wp->saved_time);
|
||||||
myfree((char *) wp);
|
myfree((char *) wp);
|
||||||
|
#ifdef USE_WATCHDOG_PIPE
|
||||||
|
if (watchdog_curr == 0) {
|
||||||
|
event_disable_readwrite(watchdog_pipe[0]);
|
||||||
|
(void) close(watchdog_pipe[0]);
|
||||||
|
(void) close(watchdog_pipe[1]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (msg_verbose > 1)
|
if (msg_verbose > 1)
|
||||||
msg_info("%s: %p", myname, (void *) wp);
|
msg_info("%s: %p", myname, (void *) wp);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user