permit_tls_all_clientcerts, and check_address_map (the last
one is used in local_header_rewrite_clients only). File:
smtpd/smtpd_check.c.
+
+20110729
+
+ Workaround: some getpwnam() and getpwuid() implementations
+ cause mail to bounce ("user unknown") after LDAP etc. lookup
+ error. Postfix now uses POSIX getpwnam_r() and getpwuid_r()
+ where available. Initially, this workaround supports FreeBSD,
+ Solaris and Linux. Files: makedefs, util/sys_defs.h,
+ global/mypwd.[hc], local/alias.c, local/dotforward.c,
+ local/include.c, local/mailbox.c, local/recipient.c.
+
+20110731
+
+ MacOS X 10.5 supports POSIX getpwnam_r() and getpwuid_r()
+ (source: MacOS manpages at www.freebsd.org). If MacOS turns
+ out to make a false promise, then we will undo this change.
+ Files: makedefs, util/sys_defs.h.
+
+20110810
+
+ Cleanup: optimize an optimization to avoid uid->name lookup
+ when all users are authorized with authorized_submit_users,
+ authorized_mailq_users, authorized_flush_users. File:
+ global/user_acl.c.
+
+20110811
+
+ Workaround: report a {client_connections} Milter macro value
+ of zero instead of garbage, when the remote SMTP client is
+ excluded from connection count limits. Problem reported by
+ Christian Roessner. File: smtpd/smtpd_state,c,
Make the rules for how to use close-on-exec more explicit.
+ Add SASL / TLS note to BASIC_CONFIGURATION_README.html#relay_from.
+
Trick from amavisd: save listen socket/fifo/etc state, clear
their close-on-exec flags, exec the same program file to
re-initialize (with saved socket state on command line or
<b>postconf</b> [<b>-btv</b>] [<b>-c</b> <i>config</i><b>_</b><i>dir</i>] [<i>template</i><b>_</b><i>file</i>]
<b>DESCRIPTION</b>
- The <a href="postconf.1.html"><b>postconf</b>(1)</a> command displays the actual values of con-
- figuration parameters, changes configuration parameter
- values, or displays other configuration information about
+ The <a href="postconf.1.html"><b>postconf</b>(1)</a> command displays the values of configura-
+ tion parameters by default. It can also change parameter
+ values, or display other configuration information about
the Postfix mail system.
Options:
With Postfix version 2.8 and later, the <b>-e</b> is no
longer needed.
- <b>-h</b> Show parameter values only, not the "<i>name =</i> " label
- that normally precedes the value.
+ <b>-h</b> Show parameter values only; do not prepend the
+ "<i>name =</i> " label that normally precedes the value.
<b>-l</b> List the names of all supported mailbox locking
methods. Postfix supports the following methods:
# Do not build with PCRE support.
# By default, PCRE support is compiled in when the \fBpcre-config\fR
# utility is installed.
+# .IP \fB-DNO_POSIX_GETPW_R\fR
+# Disable support for POSIX getpwnam_r/getpwuid_r.
# .IP \fB-DNO_SIGSETJMP\fR
# Use setjmp()/longjmp() instead of sigsetjmp()/siglongjmp().
# By default, Postfix uses sigsetjmp()/siglongjmp() when they
;;
OpenBSD.4*) SYSTYPE=OPENBSD4
;;
+ OpenBSD.5*) SYSTYPE=OPENBSD5
+ ;;
ekkoBSD.1*) SYSTYPE=EKKOBSD1
;;
NetBSD.1*) SYSTYPE=NETBSD1
SYSLIBS="-lresolv -lsocket -lnsl"
# Stock awk breaks with >10 files.
test -x /usr/xpg4/bin/awk && AWK=/usr/xpg4/bin/awk
- # Solaris 2.5 added usleep() and POSIX regular expressions
+ # Solaris 2.5 added usleep(), POSIX regexp, POSIX getpwnam/uid_r
case $RELEASE in
- 5.[0-4]) CCARGS="$CCARGS -DMISSING_USLEEP -DNO_POSIX_REGEXP";;
+ 5.[0-4]) CCARGS="$CCARGS -DMISSING_USLEEP -DNO_POSIX_REGEXP -DNO_POSIX_GETPW_R";;
esac
# Solaris 8 added IPv6 and /dev/poll
case $RELEASE in
[1-6].*) CCARGS="$CCARGS -DNO_IPV6";;
*) CCARGS="$CCARGS -DBIND_8_COMPAT -DNO_NETINFO";;
esac
+ # Darwin 9.0 (MacOS X 10.5) adds POSIX getpwnam_r/getpwuid_r
+ case $RELEASE in
+ [1-8].*) CCARGS="$CCARGS -DNO_POSIX_GETPW_R";;
+ esac
# Darwin 10.3.0 no longer has <nameser8_compat.h>.
case $RELEASE in
?.*) CCARGS="$CCARGS -DRESOLVE_H_NEEDS_NAMESER8_COMPAT_H";;
.SH DESCRIPTION
.ad
.fi
-The \fBpostconf\fR(1) command displays the actual values
-of configuration parameters, changes configuration parameter
-values, or displays other configuration information about
-the Postfix mail system.
+The \fBpostconf\fR(1) command displays the values of
+configuration parameters by default. It can also change
+parameter values, or display other configuration information
+about the Postfix mail system.
Options:
.IP \fB-a\fR
With Postfix version 2.8 and later, the \fB-e\fR is no
longer needed.
.IP \fB-h\fR
-Show parameter values only, not the "\fIname = \fR" label
-that normally precedes the value.
+Show parameter values only; do not prepend the "\fIname =
+\fR" label that normally precedes the value.
.IP \fB-l\fR
List the names of all supported mailbox locking methods.
Postfix supports the following methods:
trace.o: recipient_list.h
trace.o: trace.c
trace.o: trace.h
+user_acl.o: ../../include/dict_static.h
user_acl.o: ../../include/match_list.h
user_acl.o: ../../include/match_ops.h
user_acl.o: ../../include/sys_defs.h
user_acl.o: ../../include/vbuf.h
user_acl.o: ../../include/vstring.h
-user_acl.o: mail_params.h
user_acl.o: mypwd.h
user_acl.o: string_list.h
user_acl.o: user_acl.c
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20110706"
+#define MAIL_RELEASE_DATE "20110814"
#define MAIL_VERSION_NUMBER "2.9"
#ifdef SNAPSHOT
/* NAME
/* mypwd 3
/* SUMMARY
-/* caching getpwnam()/getpwuid()
+/* caching getpwnam_r()/getpwuid_r()
/* SYNOPSIS
/* #include <mypwd.h>
/*
-/* struct mypasswd *mypwuid(uid)
+/* int mypwuid_err(uid, pwd)
/* uid_t uid;
+/* struct mypasswd **pwd;
/*
-/* struct mypasswd *mypwnam(name)
+/* int mypwnam_err(name, pwd)
/* const char *name;
+/* struct mypasswd **pwd;
/*
/* void mypwfree(pwd)
/* struct mypasswd *pwd;
+/* BACKWARDS COMPATIBILITY
+/* struct mypasswd *mypwuid(uid)
+/* uid_t uid;
+/*
+/* struct mypasswd *mypwnam(name)
+/* const char *name;
/* DESCRIPTION
/* This module maintains a reference-counted cache of password
-/* database lookup results. The idea is to avoid surprises by
-/* getpwnam() or getpwuid() overwriting a previous result, while
-/* at the same time avoiding duplicate copies of password
-/* information in memory, and to avoid making repeated getpwxxx()
-/* calls for the same information.
+/* database lookup results. The idea is to avoid making repeated
+/* getpw*() calls for the same information.
+/*
+/* mypwnam_err() and mypwuid_err() are wrappers that cache a
+/* private copy of results from the getpwnam_r() and getpwuid_r()
+/* library routines (on legacy systems: from getpwnam() and
+/* getpwuid(). Note: cache updates are not protected by mutex.
/*
-/* mypwnam() and mypwuid() are wrappers that cache a private copy
-/* of results from the getpwnam() and getpwuid() library routines.
/* Results are shared between calls with the same \fIname\fR
/* or \fIuid\fR argument, so changing results is verboten.
/*
-/* mypwfree() cleans up the result of mypwnam() and mypwuid().
+/* mypwnam() and mypwuid() are binary-compatibility wrappers
+/* for legacy applications.
+/*
+/* mypwfree() cleans up the result of mypwnam*() and mypwuid*().
/* BUGS
/* This module is security sensitive and complex at the same
/* time, which is bad.
+/* DIAGNOSTICS
+/* mypwnam_err() and mypwuid_err() return a non-zero system
+/* error code when the lookup could not be performed. They
+/* return zero, plus a null struct mypasswd pointer, when the
+/* requested information was not found.
+/*
+/* Fatal error: out of memory.
/* LICENSE
/* .ad
/* .fi
/* System library. */
#include <sys_defs.h>
-#include <pwd.h>
+#include <unistd.h>
#include <string.h>
#ifdef USE_PATHS_H
#include <paths.h>
#endif
+#include <errno.h>
/* Utility library. */
#include "mypwd.h"
+ /*
+ * Workaround: Solaris >= 2.5.1 provides two getpwnam_r() and getpwuid_r()
+ * implementations. The default variant is compatible with historical
+ * Solaris implementations. The non-default variant is POSIX-compliant.
+ *
+ * To get the POSIX-compliant variant, we include the file <pwd.h> after
+ * defining _POSIX_PTHREAD_SEMANTICS. We do this after all other includes,
+ * so that we won't unexpectedly affect any other APIs.
+ *
+ * This happens to work because nothing above this includes <pwd.h>, and
+ * because of the specific way that Solaris redefines getpwnam_r() and
+ * getpwuid_r() for POSIX compliance. We know the latter from peeking under
+ * the hood. What we do is only marginally better than directly invoking
+ * __posix_getpwnam_r() and __posix_getpwuid_r().
+ */
+#ifdef GETPW_R_NEEDS_POSIX_PTHREAD_SEMANTICS
+#define _POSIX_PTHREAD_SEMANTICS
+#endif
+#include <pwd.h>
+
/*
* The private cache. One for lookups by name, one for lookups by uid, and
- * one for the last looked up result.
+ * one for the last looked up result. There is a minor problem: multiple
+ * cache entries may have the same uid value, but the cache that is indexed
+ * by uid can store only one entry per uid value.
*/
static HTABLE *mypwcache_name = 0;
static BINHASH *mypwcache_uid = 0;
static struct mypasswd *last_pwd;
+ /*
+ * XXX Solaris promises that we can determine the getpw*_r() buffer size by
+ * calling sysconf(_SC_GETPW_R_SIZE_MAX). Many systems promise that they
+ * will return an ERANGE error when the buffer is too small. However, not
+ * all systems make such promises. Therefore, we settle for the dumbest
+ * option: a large buffer. This is acceptable because the buffer is used
+ * only for short-term storage.
+ */
+#ifdef HAVE_POSIX_GETPW_R
+#define GETPW_R_BUFSIZ 1024
+#endif
+#define MYPWD_ERROR_DELAY (30)
+
/* mypwenter - enter password info into cache */
-static struct mypasswd *mypwenter(struct passwd * pwd)
+static struct mypasswd *mypwenter(const struct passwd * pwd)
{
struct mypasswd *mypwd;
mypwd->pw_gecos = mystrdup(pwd->pw_gecos);
mypwd->pw_dir = mystrdup(pwd->pw_dir);
mypwd->pw_shell = mystrdup(*pwd->pw_shell ? pwd->pw_shell : _PATH_BSHELL);
+
+ /*
+ * Avoid mypwcache_uid memory leak when multiple names have the same UID.
+ * This makes the lookup result dependent on program history. But, it was
+ * already history-dependent before we added this extra check.
+ */
htable_enter(mypwcache_name, mypwd->pw_name, (char *) mypwd);
- binhash_enter(mypwcache_uid, (char *) &mypwd->pw_uid,
- sizeof(mypwd->pw_uid), (char *) mypwd);
+ if (binhash_locate(mypwcache_uid, (char *) &mypwd->pw_uid,
+ sizeof(mypwd->pw_uid)) == 0)
+ binhash_enter(mypwcache_uid, (char *) &mypwd->pw_uid,
+ sizeof(mypwd->pw_uid), (char *) mypwd);
return (mypwd);
}
/* mypwuid - caching getpwuid() */
struct mypasswd *mypwuid(uid_t uid)
+{
+ struct mypasswd *mypwd;
+
+ while ((errno = mypwuid_err(uid, &mypwd)) != 0) {
+ msg_warn("getpwuid_r: %m");
+ sleep(MYPWD_ERROR_DELAY);
+ }
+ return (mypwd);
+}
+
+/* mypwuid_err - caching getpwuid_r(), minus thread safety */
+
+int mypwuid_err(uid_t uid, struct mypasswd ** result)
{
struct passwd *pwd;
struct mypasswd *mypwd;
mypwfree(last_pwd);
last_pwd = 0;
} else {
- mypwd = last_pwd;
+ *result = mypwd = last_pwd;
mypwd->refcount++;
- return (mypwd);
+ return (0);
}
}
/*
- * Find the info in the cache or in the password database. Make a copy,
- * so that repeated getpwnam() calls will not clobber our result.
+ * Find the info in the cache or in the password database.
*/
if ((mypwd = (struct mypasswd *)
binhash_find(mypwcache_uid, (char *) &uid, sizeof(uid))) == 0) {
- if ((pwd = getpwuid(uid)) == 0)
+#ifdef HAVE_POSIX_GETPW_R
+ char pwstore[GETPW_R_BUFSIZ];
+ struct passwd pwbuf;
+ int err;
+
+ err = getpwuid_r(uid, &pwbuf, pwstore, sizeof(pwstore), &pwd);
+ if (err != 0)
+ return (err);
+ if (pwd == 0) {
+ *result = 0;
+ return (0);
+ }
+#else
+ if ((pwd = getpwuid(uid)) == 0) {
+ *result = 0;
return (0);
+ }
+#endif
mypwd = mypwenter(pwd);
}
- last_pwd = mypwd;
+ *result = last_pwd = mypwd;
mypwd->refcount += 2;
- return (mypwd);
+ return (0);
}
/* mypwnam - caching getpwnam() */
struct mypasswd *mypwnam(const char *name)
+{
+ struct mypasswd *mypwd;
+
+ while ((errno = mypwnam_err(name, &mypwd)) != 0) {
+ msg_warn("getpwnam_r: %m");
+ sleep(MYPWD_ERROR_DELAY);
+ }
+ return (mypwd);
+}
+
+/* mypwnam_err - caching getpwnam_r(), minus thread safety */
+
+int mypwnam_err(const char *name, struct mypasswd ** result)
{
struct passwd *pwd;
struct mypasswd *mypwd;
mypwfree(last_pwd);
last_pwd = 0;
} else {
- mypwd = last_pwd;
+ *result = mypwd = last_pwd;
mypwd->refcount++;
- return (mypwd);
+ return (0);
}
}
/*
- * Find the info in the cache or in the password database. Make a copy,
- * so that repeated getpwnam() calls will not clobber our result.
+ * Find the info in the cache or in the password database.
*/
if ((mypwd = (struct mypasswd *) htable_find(mypwcache_name, name)) == 0) {
- if ((pwd = getpwnam(name)) == 0)
+#ifdef HAVE_POSIX_GETPW_R
+ char pwstore[GETPW_R_BUFSIZ];
+ struct passwd pwbuf;
+ int err;
+
+ err = getpwnam_r(name, &pwbuf, pwstore, sizeof(pwstore), &pwd);
+ if (err != 0)
+ return (err);
+ if (pwd == 0) {
+ *result = 0;
+ return (0);
+ }
+#else
+ if ((pwd = getpwnam(name)) == 0) {
+ *result = 0;
return (0);
+ }
+#endif
mypwd = mypwenter(pwd);
}
- last_pwd = mypwd;
+ *result = last_pwd = mypwd;
mypwd->refcount += 2;
- return (mypwd);
+ return (0);
}
/* mypwfree - destroy password info */
if (mypwd->refcount < 1)
msg_panic("mypwfree: refcount %d", mypwd->refcount);
+ /*
+ * See mypwenter() for the reason behind the binhash_locate() test.
+ */
if (--mypwd->refcount == 0) {
htable_delete(mypwcache_name, mypwd->pw_name, (void (*) (char *)) 0);
- binhash_delete(mypwcache_uid, (char *) &mypwd->pw_uid,
- sizeof(mypwd->pw_uid), (void (*) (char *)) 0);
+ if (binhash_locate(mypwcache_uid, (char *) &mypwd->pw_uid,
+ sizeof(mypwd->pw_uid)))
+ binhash_delete(mypwcache_uid, (char *) &mypwd->pw_uid,
+ sizeof(mypwd->pw_uid), (void (*) (char *)) 0);
myfree(mypwd->pw_name);
myfree(mypwd->pw_passwd);
myfree(mypwd->pw_gecos);
if (argc == 1)
msg_fatal("usage: %s name or uid ...", argv[0]);
- mypwd = (struct mypasswd **) mymalloc((argc + 1) * sizeof(*mypwd));
+ mypwd = (struct mypasswd **) mymalloc((argc + 2) * sizeof(*mypwd));
+ /*
+ * Do a sequence of lookups.
+ */
for (i = 1; i < argc; i++) {
if (ISDIGIT(argv[i][0]))
mypwd[i] = mypwuid(atoi(argv[i]));
mypwd[i] = mypwnam(argv[i]);
if (mypwd[i] == 0)
msg_fatal("%s: not found", argv[i]);
- msg_info("+ %s link=%d used=%d used=%d", argv[i], mypwd[i]->refcount,
- mypwcache_name->used, mypwcache_uid->used);
+ msg_info("lookup %s %s/%d refcount=%d name_cache=%d uid_cache=%d",
+ argv[i], mypwd[i]->pw_name, mypwd[i]->pw_uid,
+ mypwd[i]->refcount, mypwcache_name->used, mypwcache_uid->used);
}
- for (i = 1; i < argc; i++) {
- msg_info("- %s link=%d used=%d used=%d", argv[i], mypwd[i]->refcount,
+ mypwd[argc] = last_pwd;
+
+ /*
+ * The following should free all entries.
+ */
+ for (i = 1; i < argc + 1; i++) {
+ msg_info("free %s/%d refcount=%d name_cache=%d uid_cache=%d",
+ mypwd[i]->pw_name, mypwd[i]->pw_uid, mypwd[i]->refcount,
mypwcache_name->used, mypwcache_uid->used);
mypwfree(mypwd[i]);
}
+ msg_info("name_cache=%d uid_cache=%d",
+ mypwcache_name->used, mypwcache_uid->used);
myfree((char *) mypwd);
return (0);
/* NAME
/* mypwnam 3h
/* SUMMARY
-/* caching getpwnam()/getpwuid()
+/* caching getpwnam_r()/getpwuid_r()
/* SYNOPSIS
/* #include <mypwd.h>
/* DESCRIPTION
char *pw_shell;
};
+extern int mypwnam_err(const char *, struct mypasswd **);
+extern int mypwuid_err(uid_t, struct mypasswd **);
extern struct mypasswd *mypwnam(const char *);
extern struct mypasswd *mypwuid(uid_t);
extern void mypwfree(struct mypasswd *);
/* Utility library. */
#include <vstring.h>
+#include <dict_static.h>
/* Global library. */
#include <string_list.h>
#include <mypwd.h>
-#include <mail_params.h> /* STATIC_ANYONE_ACL */
/* Application-specific. */
/*
* Optimize for the most common case. This also makes Postfix a little
- * more robust in the face of local infrastructure failures.
+ * more robust in the face of local infrastructure failures. Note that we
+ * only need to match the "static:" substring, not the result value.
*/
- if (strcmp(acl, STATIC_ANYONE_ACL) == 0)
+ if (strncmp(acl, DICT_TYPE_STATIC ":", sizeof(DICT_TYPE_STATIC)) == 0)
return (0);
/*
* really suitable for mixing numerical and non-numerical user
* information, because the numerical match is done in a separate pass
* from the non-numerical match. This breaks when the ! operator is used.
+ *
+ * XXX To avoid waiting until the lookup completes (e.g., LDAP or NIS down)
+ * invoke mypwuid_err(), and either change the user_acl() API to
+ * propagate the error to the caller, or treat lookup errors as fatal.
*/
if ((mypwd = mypwuid(uid)) == 0) {
name = "unknown";
dotforward.o: ../../include/attr.h
dotforward.o: ../../include/been_here.h
dotforward.o: ../../include/bounce.h
+dotforward.o: ../../include/defer.h
dotforward.o: ../../include/deliver_request.h
dotforward.o: ../../include/delivered_hdr.h
dotforward.o: ../../include/dict.h
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
+#include <errno.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
BOUNCE_ATTR(state.msg_attr));
return (YES);
}
- if ((alias_pwd = mypwuid(dict->owner.uid)) == 0) {
- msg_warn("cannot find alias database owner for %s", *cpp);
+ if ((errno = mypwuid_err(dict->owner.uid, &alias_pwd)) != 0
+ || alias_pwd == 0) {
+ msg_warn(errno ?
+ "cannot find alias database owner for %s: %m" :
+ "cannot find alias database owner for %s", *cpp);
dsb_simple(state.msg_attr.why, "4.3.0",
"cannot find alias database owner");
*statusp = defer_append(BOUNCE_FLAGS(state.request),
#include <mypwd.h>
#include <bounce.h>
+#include <defer.h>
#include <been_here.h>
#include <mail_params.h>
#include <mail_conf.h>
* Skip non-existing users. The mailbox delivery routine will catch the
* error.
*/
- if ((mypwd = mypwnam(state.msg_attr.user)) == 0)
+ if ((errno = mypwnam_err(state.msg_attr.user, &mypwd)) != 0) {
+ msg_warn("error looking up passwd info for %s: %m",
+ state.msg_attr.user);
+ dsb_simple(state.msg_attr.why, "4.0.0", "user lookup error");
+ *statusp = defer_append(BOUNCE_FLAGS(state.request),
+ BOUNCE_ATTR(state.msg_attr));
+ return (YES);
+ }
+ if (mypwd == 0)
return (NO);
/*
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
+#include <errno.h>
/* Utility library. */
* that is owned by their victim.
*/
if (usr_attr.uid == 0) {
- if ((file_pwd = mypwuid(st.st_uid)) == 0) {
- msg_warn("cannot find username for uid %ld", (long) st.st_uid);
+ if ((errno = mypwuid_err(st.st_uid, &file_pwd)) != 0 || file_pwd == 0) {
+ msg_warn(errno ? "cannot find username for uid %ld: %m" :
+ "cannot find username for uid %ld", (long) st.st_uid);
msg_warn("%s: cannot find :include: file owner username", path);
dsb_simple(state.msg_attr.why, "4.3.5",
"mail system configuration error");
/*
* Skip delivery when this recipient does not exist.
*/
- if ((mbox_pwd = mypwnam(state.msg_attr.user)) == 0)
- return (NO);
+ if ((errno = mypwnam_err(state.msg_attr.user, &mbox_pwd)) != 0) {
+ msg_warn("error looking up passwd info for %s: %m",
+ state.msg_attr.user);
+ dsb_simple(state.msg_attr.why, "4.0.0", "user lookup error");
+ *statusp = defer_append(BOUNCE_FLAGS(state.request),
+ BOUNCE_ATTR(state.msg_attr));
+ return (YES);
+ }
+ if (mbox_pwd == 0)
+ return (NO);
/*
* No early returns or we have a memory leak.
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
+#include <errno.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
* $HOME/.forward file, then mailbox delivery. Back off when the user's
* home directory does not exist.
*/
+ mypwd = 0;
if (var_stat_home_dir
- && (mypwd = mypwnam(state.msg_attr.user)) != 0
- && stat_as(mypwd->pw_dir, &st, mypwd->pw_uid, mypwd->pw_gid) < 0) {
- dsb_simple(state.msg_attr.why, "4.3.0",
- "cannot access home directory %s: %m", mypwd->pw_dir);
+ && (errno = mypwnam_err(state.msg_attr.user, &mypwd)) != 0) {
+ msg_warn("error looking up passwd info for %s: %m",
+ state.msg_attr.user);
+ dsb_simple(state.msg_attr.why, "4.0.0", "user lookup error");
return (defer_append(BOUNCE_FLAGS(state.request),
BOUNCE_ATTR(state.msg_attr)));
}
+ if (mypwd != 0) {
+ if (stat_as(mypwd->pw_dir, &st, mypwd->pw_uid, mypwd->pw_gid) < 0) {
+ dsb_simple(state.msg_attr.why, "4.3.0",
+ "cannot access home directory %s: %m", mypwd->pw_dir);
+ mypwfree(mypwd);
+ return (defer_append(BOUNCE_FLAGS(state.request),
+ BOUNCE_ATTR(state.msg_attr)));
+ }
+ mypwfree(mypwd);
+ }
if (deliver_dotforward(state, usr_attr, &status) == 0
&& deliver_mailbox(state, usr_attr, &status) == 0)
status = deliver_unknown(state, usr_attr);
/*
/* \fBpostconf\fR [\fB-btv\fR] [\fB-c \fIconfig_dir\fR] [\fItemplate_file\fR]
/* DESCRIPTION
-/* The \fBpostconf\fR(1) command displays the actual values
-/* of configuration parameters, changes configuration parameter
-/* values, or displays other configuration information about
-/* the Postfix mail system.
+/* The \fBpostconf\fR(1) command displays the values of
+/* configuration parameters by default. It can also change
+/* parameter values, or display other configuration information
+/* about the Postfix mail system.
/*
/* Options:
/* .IP \fB-a\fR
/* With Postfix version 2.8 and later, the \fB-e\fR is no
/* longer needed.
/* .IP \fB-h\fR
-/* Show parameter values only, not the "\fIname = \fR" label
-/* that normally precedes the value.
+/* Show parameter values only; do not prepend the "\fIname =
+/* \fR" label that normally precedes the value.
/* .IP \fB-l\fR
/* List the names of all supported mailbox locking methods.
/* Postfix supports the following methods:
state->service = mystrdup(service);
state->buffer = vstring_alloc(100);
state->addr_buf = vstring_alloc(100);
+ state->conn_count = state->conn_rate = 0;
state->error_count = 0;
state->error_mask = 0;
state->notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
|| defined(FREEBSD8) \
|| defined(BSDI2) || defined(BSDI3) || defined(BSDI4) \
|| defined(OPENBSD2) || defined(OPENBSD3) || defined(OPENBSD4) \
+ || defined(OPENBSD5) \
|| defined(NETBSD1) || defined(NETBSD2) || defined(NETBSD3) \
|| defined(NETBSD4) \
|| defined(EKKOBSD1)
# endif
#endif
+#ifndef NO_POSIX_GETPW_R
+# if (defined(__FreeBSD_version) && __FreeBSD_version >= 510000) \
+ || (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 300000000) \
+ || (defined(OpenBSD) && OpenBSD >= 200811) /* OpenBSD 4.4 */
+# define HAVE_POSIX_GETPW_R
+# endif
+#endif
+
#endif
/*
# define EVENTS_STYLE EVENTS_STYLE_KQUEUE
# define USE_SYSV_POLL
#endif
+#ifndef NO_POSIX_GETPW_R
+# define HAVE_POSIX_GETPW_R
+#endif
#endif
#ifndef NO_DEVPOLL
# define EVENTS_STYLE EVENTS_STYLE_DEVPOLL
#endif
+#ifndef NO_POSIX_GETPW_R
+# define HAVE_POSIX_GETPW_R
+# define GETPW_R_NEEDS_POSIX_PTHREAD_SEMANTICS
+#endif
/*
* Allow build environment to override paths.
# define EVENTS_STYLE EVENTS_STYLE_EPOLL /* introduced in 2.5 */
#endif
#define USE_SYSV_POLL
+#ifndef NO_POSIX_GETPW_R
+# if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 1) \
+ || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 1) \
+ || (defined(_BSD_SOURCE) && _BSD_SOURCE >= 1) \
+ || (defined(_SVID_SOURCE) && _SVID_SOURCE >= 1) \
+ || (defined(_POSIX_SOURCE) && _POSIX_SOURCE >= 1)
+# define HAVE_POSIX_GETPW_R
+# endif
+#endif
+
#endif
#ifdef LINUX1
#define NORMAL_EXIT_STATUS(status) ((status) == 0)
#endif
+#ifdef NO_POSIX_GETPW_R
+#undef HAVE_POSIX_GETPW_R
+#endif
+
#ifndef OCTAL_TO_UNSIGNED
#define OCTAL_TO_UNSIGNED(res, str) ((res) = strtoul((str), (char **) 0, 8))
#endif