world. Based on code by Branko F. Gracnar. Files:
smtpd/smtpd.c, and documentation.
+20050407
+
+ @%^!#& Thanks to inadequate SASL documentation the client
+ could negotiate a security layer where none was desired.
+ Better documentation has become available since Postfix
+ SASL support was implemented, and now Postfix needs to be
+ fixed. Files: */*_sasl_glue.c.
+
+20050409
+
+ Safety: the CDB map now logs a warning when the source file
+ is newer than the indexed file, just like the Berkeley DB
+ and DBM maps. Michael Tokarev. File: util/dict_cdb.c.
+
+20040411
+
+ Portability: put the SASL DLL Hell guard after the declarations
+ instead of before. Reported by Marcus Grando. Files:
+ smtp/smtp_sasl_glue.c, lmtp/lmtp_sasl_glue.c.
+
+20050412
+
+ Infrastructure: change the disposition or other properties
+ of an embryonic queue file. This is currently used only to
+ place mail on hold. After code by Victor Duchovni. Files:
+ global/mail_stream.[hc], cleanup/cleanup_api.c.
+
+20040513
+
+ Portability: don't mix socket message send/receive calls
+ with socket stream read/write calls. The fact that you can
+ get away with it only on some stacks implies that there is
+ no long-term guarantee. Specify -DCAN_WRITE_BEFORE_SENDING_FD
+ if you feel brave. File: util/sys_defs.h.
+
+ Robustness: re-compile all object files after the "make
+ makefiles" options have changed. Files: src/*/Makefile.in.
+
Open problems:
Med: disable header address rewriting after XCLIENT?
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt" whenever you change the
transport table.
+In some installations, there may be separate instances of Postfix processing
+inbound and outbound mail on a multi-homed firewall. The inbound Postfix
+instance has an SMTP server listening on the external firewall interface, and
+the outbound Postfix instance has an SMTP server listening on the internal
+interface. In such a configuration is it is tempting to configure
+$inet_interfaces in each instance with just the corresponding interface
+address.
+
+In most cases, using inet_interfaces in this way will not work, because as
+documented in the $inet_interfaces reference manual, the smtp(8) delivery agent
+will also use the specified interface address as the source address for
+outbound connections and will be unable to reach hosts on "the other side" of
+the firewall. The symptoms are that the firewall is unable to connect to hosts
+that are in fact up. See the inet_interfaces parameter documentation for
+suggested work-arounds.
+
D\bDe\bel\bli\biv\bve\ber\bri\bin\bng\bg s\bso\bom\bme\be b\bbu\but\bt n\bno\bot\bt a\bal\bll\bl a\bac\bcc\bco\bou\bun\bnt\bts\bs l\blo\boc\bca\bal\bll\bly\by
A drawback of sending mail as "user@example.com" (instead of
listed in $mydestination, or when it matches $inet_interfaces or
$proxy_interfaces.
-In some installations, there may be separate instances of Postfix processing
-inbound and outbound mail on a multi-homed firewall. The inbound Postfix
-instance has an SMTP server listening on the external firewall interface, and
-the outbound Postfix instance has an SMTP server listening on the internal
-interface. In such a configuration is it is tempting to configure
-$inet_interfaces in each instance with just the corresponding interface
-address.
-
-In most cases, using inet_interfaces in this way will not work, because as
-documented in the $inet_interfaces reference manual, the smtp(8) delivery agent
-will also use the specified interface address as the source address for
-outbound connections and will be unable to reach hosts on "the other side" of
-the firewall. The symptoms are that the firewall is unable to connect to hosts
-that are in fact up. See the inet_interfaces parameter documentation for
-suggested work-arounds.
-
R\bRu\bun\bnn\bni\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx b\bbe\beh\bhi\bin\bnd\bd a\ba f\bfi\bir\bre\bew\bwa\bal\bll\bl
The simplest way to set up Postfix on a host behind a firewalled network is to
The logging format has changed. Postfix delivery agents now log the
RFC 3463 enhanced status code as "dsn=x.y.z" where y and z can be
-up to three digits each.
+up to three digits each. See the file pfloggsum-dsn-patch for an
+update to the pfloggsum script.
After you upgrade from Postfix 2.2 or 2.3 you need to execute
"postfix reload", otherwise you will keep running the old Postfix
#
# DESCRIPTION
# The optional virtual(5) alias table rewrites recipient
-# addresses for all local, virtual and remote mail destina-
-# tions. This is unlike the aliases(5) table which is used
-# only for local(8) delivery. Virtual aliasing is recur-
-# sive, and is implemented by the Postfix cleanup(8) daemon
-# before mail is queued.
+# addresses for all local, all virtual, and all remote mail
+# destinations. This is unlike the aliases(5) table which
+# is used only for local(8) delivery. Virtual aliasing is
+# recursive, and is implemented by the Postfix cleanup(8)
+# daemon before mail is queued.
#
# The main applications of virtual aliasing are:
#
<p> Execute the command "<b>postmap /etc/postfix/transport</b>"
whenever you change the transport table. </p>
+<p> In some installations, there may be separate instances of Postfix
+processing inbound and outbound mail on a multi-homed firewall. The
+inbound Postfix instance has an SMTP server listening on the external
+firewall interface, and the outbound Postfix instance has an SMTP server
+listening on the internal interface. In such a configuration is it is
+tempting to configure $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> in each instance with just the
+corresponding interface address. </p>
+
+<p> In most cases, using <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> in this way will not work,
+because as documented in the $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> reference manual, the
+<a href="smtp.8.html">smtp(8)</a> delivery agent will also use the specified interface address
+as the source address for outbound connections and will be unable to
+reach hosts on "the other side" of the firewall. The symptoms are that
+the firewall is unable to connect to hosts that are in fact up. See the
+<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> parameter documentation for suggested work-arounds.</p>
+
<h2><a name="some_local">Delivering some but not all accounts
locally</a></h2>
</ul>
-<p> In some installations, there may be separate instances of Postfix
-processing inbound and outbound mail on a multi-homed firewall. The
-inbound Postfix instance has an SMTP server listening on the external
-firewall interface, and the outbound Postfix instance has an SMTP server
-listening on the internal interface. In such a configuration is it is
-tempting to configure $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> in each instance with just the
-corresponding interface address. </p>
-
-<p> In most cases, using <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> in this way will not work,
-because as documented in the $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> reference manual, the
-<a href="smtp.8.html">smtp(8)</a> delivery agent will also use the specified interface address
-as the source address for outbound connections and will be unable to
-reach hosts on "the other side" of the firewall. The symptoms are that
-the firewall is unable to connect to hosts that are in fact up. See the
-<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> parameter documentation for suggested work-arounds.</p>
-
<h2><a name="intranet">Running Postfix behind a firewall</a></h2>
<p> The simplest way to set up Postfix on a host behind a firewalled
<b>STANDARDS</b>
<a href="http://www.faqs.org/rfcs/rfc822.html">RFC 822</a> (ARPA Internet Text Messages)
+ <a href="http://www.faqs.org/rfcs/rfc1892.html">RFC 1892</a> (Delivery Status Notifications)
<a href="http://www.faqs.org/rfcs/rfc1894.html">RFC 1894</a> (Delivery Status Notifications)
<a href="http://www.faqs.org/rfcs/rfc2045.html">RFC 2045</a> (Format of Internet Message Bodies)
The maximal time between attempts to deliver a deferred message.
</p>
+<p> This parameter should be set to a value greater than or equal
+to $<a href="postconf.5.html#minimal_backoff_time">minimal_backoff_time</a>. See also $<a href="postconf.5.html#queue_run_delay">queue_run_delay</a>. </p>
+
<p>
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
The default time unit is s (seconds).
kept in the short-term, in-memory, destination status cache.
</p>
+<p> It is recommended that this parameter be set greater than or
+equal to $<a href="postconf.5.html#queue_run_delay">queue_run_delay</a>. See also $<a href="postconf.5.html#maximal_backoff_time">maximal_backoff_time</a>. </p>
+
<p>
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
The default time unit is s (seconds).
The time between <a href="QSHAPE_README.html#deferred_queue">deferred queue</a> scans by the queue manager.
</p>
+<p> It is recommended that this parameter be set less than or equal
+to $<a href="postconf.5.html#minimal_backoff_time">minimal_backoff_time</a>. See also $<a href="postconf.5.html#maximal_backoff_time">maximal_backoff_time</a>. </p>
+
<p>
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
The default time unit is s (seconds).
<b>DESCRIPTION</b>
The optional <a href="virtual.5.html"><b>virtual</b>(5)</a> alias table rewrites recipient
- addresses for all local, virtual and remote mail destina-
- tions. This is unlike the <a href="aliases.5.html"><b>aliases</b>(5)</a> table which is used
- only for <a href="local.8.html"><b>local</b>(8)</a> delivery. Virtual aliasing is recur-
- sive, and is implemented by the Postfix <a href="cleanup.8.html"><b>cleanup</b>(8)</a> daemon
- before mail is queued.
+ addresses for all local, all virtual, and all remote mail
+ destinations. This is unlike the <a href="aliases.5.html"><b>aliases</b>(5)</a> table which
+ is used only for <a href="local.8.html"><b>local</b>(8)</a> delivery. Virtual aliasing is
+ recursive, and is implemented by the Postfix <a href="cleanup.8.html"><b>cleanup</b>(8)</a>
+ daemon before mail is queued.
The main applications of virtual aliasing are:
.SH maximal_backoff_time (default: 4000s)
The maximal time between attempts to deliver a deferred message.
.PP
+This parameter should be set to a value greater than or equal
+to $minimal_backoff_time. See also $queue_run_delay.
+.PP
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
The default time unit is s (seconds).
.SH maximal_queue_lifetime (default: 5d)
This parameter also limits the time an unreachable destination is
kept in the short-term, in-memory, destination status cache.
.PP
+It is recommended that this parameter be set greater than or
+equal to $queue_run_delay. See also $maximal_backoff_time.
+.PP
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
The default time unit is s (seconds).
.SH multi_recipient_bounce_reject_code (default: 550)
.SH queue_run_delay (default: 1000s)
The time between deferred queue scans by the queue manager.
.PP
+It is recommended that this parameter be set less than or equal
+to $minimal_backoff_time. See also $maximal_backoff_time.
+.PP
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
The default time unit is s (seconds).
.SH queue_service_name (default: qmgr)
.ad
.fi
The optional \fBvirtual\fR(5) alias table rewrites recipient
-addresses for all local, virtual and remote mail destinations.
+addresses for all local, all virtual, and all remote mail
+destinations.
This is unlike the \fBaliases\fR(5) table which is used
only for \fBlocal\fR(8) delivery. Virtual aliasing is
recursive, and is implemented by the Postfix \fBcleanup\fR(8)
.na
.nf
RFC 822 (ARPA Internet Text Messages)
+RFC 1892 (Delivery Status Notifications)
RFC 1894 (Delivery Status Notifications)
RFC 2045 (Format of Internet Message Bodies)
.SH DIAGNOSTICS
--- /dev/null
+Postfix 2.3 changes the logging format, introducing a field that
+reports the delivery status code as "dsn=x.yy.zz", where yy and zz
+can be up to three digits long. This breaks pflogsumm analysis.
+
+The patch below appeared in:
+
+ Message-ID: <4257CF98.10309@michaweb.net>
+ Date: Sat, 09 Apr 2005 14:50:32 +0200
+ From: John Fawcett <johnml@michaweb.net>
+ To: postfix-users@postfix.org
+ Subject: postfix 2.3 and pflogsumm
+
+--- pflogsumm.original 2005-04-09 12:54:44.140532258 +0200
++++ pflogsumm 2005-04-09 12:55:33.246949650 +0200
+@@ -696,7 +696,7 @@
+ }
+ }
+ elsif((($addr, $relay, $delay, $status, $toRmdr) = $logRmdr =~
+- /to=<([^>]*)>, (?:orig_to=<[^>]*>, )?relay=([^,]+), delay=([^,]+), status=(\S+)(.*)$/o) >= 4)
++ /to=<([^>]*)>, (?:orig_to=<[^>]*>, )?relay=([^,]+), delay=([^,]+), (?:dsn=\d+\.\d+\.\d+, )?status=(\S+)(.*)$/o) >= 4)
+ {
+
+ if($opts{'m'} && $addr =~ /^(.*!)*([^!]+)!([^!@]+)@([^\.]+)$/o) {
<p> Execute the command "<b>postmap /etc/postfix/transport</b>"
whenever you change the transport table. </p>
+<p> In some installations, there may be separate instances of Postfix
+processing inbound and outbound mail on a multi-homed firewall. The
+inbound Postfix instance has an SMTP server listening on the external
+firewall interface, and the outbound Postfix instance has an SMTP server
+listening on the internal interface. In such a configuration is it is
+tempting to configure $inet_interfaces in each instance with just the
+corresponding interface address. </p>
+
+<p> In most cases, using inet_interfaces in this way will not work,
+because as documented in the $inet_interfaces reference manual, the
+smtp(8) delivery agent will also use the specified interface address
+as the source address for outbound connections and will be unable to
+reach hosts on "the other side" of the firewall. The symptoms are that
+the firewall is unable to connect to hosts that are in fact up. See the
+inet_interfaces parameter documentation for suggested work-arounds.</p>
+
<h2><a name="some_local">Delivering some but not all accounts
locally</a></h2>
</ul>
-<p> In some installations, there may be separate instances of Postfix
-processing inbound and outbound mail on a multi-homed firewall. The
-inbound Postfix instance has an SMTP server listening on the external
-firewall interface, and the outbound Postfix instance has an SMTP server
-listening on the internal interface. In such a configuration is it is
-tempting to configure $inet_interfaces in each instance with just the
-corresponding interface address. </p>
-
-<p> In most cases, using inet_interfaces in this way will not work,
-because as documented in the $inet_interfaces reference manual, the
-smtp(8) delivery agent will also use the specified interface address
-as the source address for outbound connections and will be unable to
-reach hosts on "the other side" of the firewall. The symptoms are that
-the firewall is unable to connect to hosts that are in fact up. See the
-inet_interfaces parameter documentation for suggested work-arounds.</p>
-
<h2><a name="intranet">Running Postfix behind a firewall</a></h2>
<p> The simplest way to set up Postfix on a host behind a firewalled
The maximal time between attempts to deliver a deferred message.
</p>
+<p> This parameter should be set to a value greater than or equal
+to $minimal_backoff_time. See also $queue_run_delay. </p>
+
<p>
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
The default time unit is s (seconds).
kept in the short-term, in-memory, destination status cache.
</p>
+<p> It is recommended that this parameter be set greater than or
+equal to $queue_run_delay. See also $maximal_backoff_time. </p>
+
<p>
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
The default time unit is s (seconds).
The time between deferred queue scans by the queue manager.
</p>
+<p> It is recommended that this parameter be set less than or equal
+to $minimal_backoff_time. See also $maximal_backoff_time. </p>
+
<p>
Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
The default time unit is s (seconds).
# \fBpostmap -q - /etc/postfix/virtual <\fIinputfile\fR
# DESCRIPTION
# The optional \fBvirtual\fR(5) alias table rewrites recipient
-# addresses for all local, virtual and remote mail destinations.
+# addresses for all local, all virtual, and all remote mail
+# destinations.
# This is unlike the \fBaliases\fR(5) table which is used
# only for \fBlocal\fR(8) delivery. Virtual aliasing is
# recursive, and is implemented by the Postfix \fBcleanup\fR(8)
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
/* themselves, and that depend on retry logic in their own client.
/* STANDARDS
/* RFC 822 (ARPA Internet Text Messages)
+/* RFC 1892 (Delivery Status Notifications)
/* RFC 1894 (Delivery Status Notifications)
/* RFC 2045 (Format of Internet Message Bodies)
/* DIAGNOSTICS
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
CLEANUP_STATE *state;
int flags;
int type = 0;
+ int status;
/*
* Sanity check. This service takes no command-line arguments.
/*
* Finish this message, and report the result status to the client.
*/
+ status = cleanup_flush(state); /* in case state is modified */
attr_print(src, ATTR_FLAG_NONE,
- ATTR_TYPE_NUM, MAIL_ATTR_STATUS, cleanup_flush(state),
+ ATTR_TYPE_NUM, MAIL_ATTR_STATUS, status,
ATTR_TYPE_STR, MAIL_ATTR_WHY, state->reason ?
state->reason : "",
ATTR_TYPE_END);
#include <bounce.h>
#include <mail_params.h>
#include <mail_stream.h>
-#include <hold_message.h>
+#include <mail_flow.h>
#include <dsn_util.h>
/* Application-specific. */
*/
if (state->errs == 0 && (state->flags & CLEANUP_FLAG_DISCARD) == 0) {
if ((state->flags & CLEANUP_FLAG_HOLD) != 0) {
- if (hold_message(state->temp1, state->queue_name, state->queue_id) < 0)
- msg_fatal("%s: problem putting message on hold: %m",
- state->queue_id);
+ mail_stream_ctl(state->handle,
+ MAIL_STREAM_CTL_QUEUE, MAIL_QUEUE_HOLD,
+ MAIL_STREAM_CTL_CLASS, 0,
+ MAIL_STREAM_CTL_SERVICE, 0,
+ MAIL_STREAM_CTL_END);
junk = cleanup_path;
- cleanup_path = mystrdup(vstring_str(state->temp1));
+ cleanup_path = mystrdup(VSTREAM_PATH(state->handle->stream));
myfree(junk);
- vstream_control(state->handle->stream,
- VSTREAM_CTL_PATH, cleanup_path,
- VSTREAM_CTL_END);
+
+ /*
+ * XXX: When delivering to a non-incoming queue, do not consume
+ * in_flow tokens. Unfortunately we can't move the code that
+ * consumes tokens until after the mail is received, because that
+ * would increase the risk of duplicate deliveries.
+ */
+ (void) mail_flow_put(1);
}
state->errs = mail_stream_finish(state->handle, (VSTRING *) 0);
} else {
/* System library. */
#include <sys_defs.h>
+#include <signal.h>
/* Utility library. */
void cleanup_all(void)
{
- if (cleanup_path && REMOVE(cleanup_path))
- msg_warn("cleanup_all: remove %s: %m", cleanup_path);
+
+ /*
+ * msg_fatal() is safe against calling itself recursively, but signals
+ * need extra safety.
+ */
+ if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
+ if (cleanup_path && REMOVE(cleanup_path)) {
+ msg_warn("cleanup_all: remove %s: %m", cleanup_path);
+ cleanup_path = 0;
+ }
+ }
}
/* cleanup_pre_jail - initialize before entering the chroot jail */
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
all: $(LIB)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
all: $(PROG)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
all: $(LIB)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
/* int mail_stream_finish(info, why)
/* MAIL_STREAM *info;
/* VSTRING *why;
+/*
+/* void mail_stream_ctl(info, op, ...)
+/* MAIL_STREAM *info;
+/* int op;
/* DESCRIPTION
/* This module provides a generic interface to Postfix queue file
/* format messages to file, to Postfix server, or to external command.
/* mail_stream_file() opens a mail stream to a newly-created file and
/* arranges for trigger delivery at finish time. This call never fails.
/* But it may take forever. The mode argument specifies additional
-/* file permissions that will be OR-ed in.
+/* file permissions that will be OR-ed in when the file is finished.
+/* While embryonic files have mode 0600, finished files have mode 0700.
/*
/* mail_stream_command() opens a mail stream to external command,
/* and receives queue ID information from the command. The result
/* The result is any of the status codes defined in <cleanup_user.h>.
/* It is up to the caller to remove incomplete file objects.
/* The why argument can be a null pointer.
+/*
+/* mail_stream_ctl() selectively overrides information that
+/* was specified with mail_stream_file(); none of the attributes
+/* are applicable for other mail stream types. The arguments
+/* are a list of (operation, value) pairs, terminated with
+/* MAIL_STREAM_CTL_END. The following lists the operation
+/* codes and the types of the corresponding value arguments.
+/* .IP "MAIL_STREAM_CTL_QUEUE (char *)"
+/* The argument specifies an alternate destination queue. The
+/* queue file is moved to the specified queue before the call
+/* returns. Failure to rename the queue file results in a fatal
+/* error.
+/* .IP "MAIL_STREAM_CTL_CLASS (char *)"
+/* The argument specifies an alternate trigger class.
+/* .IP "MAIL_STREAM_CTL_SERVICE (char *)"
+/* The argument specifies an alternate trigger service.
+/* .IP "MAIL_STREAM_CTL_MODE (int)"
+/* The argument specifies an altername file mode.
/* LICENSE
/* .ad
/* .fi
#include <errno.h>
#include <utime.h>
#include <string.h>
+#include <stdarg.h>
/* Utility library. */
#include <vstream.h>
#include <stringops.h>
#include <argv.h>
+#include <sane_fsops.h>
/* Global library. */
static VSTRING *id_buf;
-#define FREE_AND_WIPE(free, arg) { if (arg) free(arg); arg = 0; }
+#define FREE_AND_WIPE(free, arg) do { if (arg) free(arg); arg = 0; } while (0)
+
+#define STR(x) vstring_str(x)
/* mail_stream_cleanup - clean up after success or failure */
static int mail_stream_finish_file(MAIL_STREAM *info, VSTRING *unused_why)
{
- int status = 0;
+ int status = CLEANUP_STAT_OK;
static char wakeup[] = {TRIGGER_REQ_WAKEUP};
struct stat st;
time_t now;
static int incoming_fs_clock_ok = 0;
static int incoming_clock_warned = 0;
int check_incoming_fs_clock;
+ int err;
/*
* Make sure the message makes it to file. Set the execute bit when no
* remote file system is not recommended, if only for performance
* reasons.
*/
- if (info->close(info->stream))
- status = (errno == EFBIG ? CLEANUP_STAT_SIZE : CLEANUP_STAT_WRITE);
+ err = info->close(info->stream);
info->stream = 0;
+ if (status == CLEANUP_STAT_OK && err != 0)
+ status = (errno == EFBIG ? CLEANUP_STAT_SIZE : CLEANUP_STAT_WRITE);
/*
* Work around file system clocks that are ahead of local time.
*/
if (path_to_reset != 0) {
- tbuf.actime = tbuf.modtime = now;
- if (utime(path_to_reset, &tbuf) < 0 && errno != ENOENT)
- msg_fatal("%s: update file time stamps: %m", info->id);
+ if (status == CLEANUP_STAT_OK) {
+ tbuf.actime = tbuf.modtime = now;
+ if (utime(path_to_reset, &tbuf) < 0 && errno != ENOENT)
+ msg_fatal("%s: update file time stamps: %m", info->id);
+ }
myfree(path_to_reset);
}
* When all is well, notify the next service that a new message has been
* queued.
*/
- if (status == CLEANUP_STAT_OK)
+ if (status == CLEANUP_STAT_OK && info->class && info->service)
mail_trigger(info->class, info->service, wakeup, sizeof(wakeup));
/*
return (info);
}
}
+
+/* mail_stream_ctl - update file-based mail stream properties */
+
+void mail_stream_ctl(MAIL_STREAM *info, int op,...)
+{
+ char *myname = "mail_stream_ctl";
+ va_list ap;
+ char *new_queue = 0;
+ char *string_value;
+
+ /*
+ * Sanity check. None of the attributes below are applicable unless the
+ * target is a file-based stream.
+ */
+ if (info->finish != mail_stream_finish_file)
+ msg_panic("%s: attempt to update non-file stream %s",
+ myname, info->id);
+
+ for (va_start(ap, op); op != MAIL_STREAM_CTL_END; op = va_arg(ap, int)) {
+
+ switch (op) {
+
+ /*
+ * Change the queue directory. We do this at the end of this
+ * call.
+ */
+ case MAIL_STREAM_CTL_QUEUE:
+ if ((new_queue = va_arg(ap, char *)) == 0)
+ msg_panic("%s: NULL queue",
+ myname);
+ break;
+
+ /*
+ * Change the service that needs to be notified.
+ */
+ case MAIL_STREAM_CTL_CLASS:
+ FREE_AND_WIPE(myfree, info->class);
+ if ((string_value = va_arg(ap, char *)) != 0)
+ info->class = mystrdup(string_value);
+ break;
+
+ case MAIL_STREAM_CTL_SERVICE:
+ FREE_AND_WIPE(myfree, info->service);
+ if ((string_value = va_arg(ap, char *)) != 0)
+ info->service = mystrdup(string_value);
+ break;
+
+ /*
+ * Change the (finished) file access mode.
+ */
+ case MAIL_STREAM_CTL_MODE:
+ info->mode = va_arg(ap, int);
+ break;
+
+ default:
+ msg_panic("%s: bad op code %d", myname, op);
+ }
+ }
+
+ /*
+ * Rename the queue file after allocating memory for new information, so
+ * that the caller can still remove an embryonic file when memory
+ * allocation fails (there is no risk of deleting the wrong file).
+ *
+ * Wietse opposed the idea to update run-time error handler information
+ * here, because this module wasn't designed to defend against internal
+ * concurrency issues with error handlers that attempt to follow dangling
+ * pointers.
+ *
+ * This code duplicates mail_queue_rename(), except that we need the new
+ * path to update the stream pathname.
+ */
+ if (new_queue != 0 && strcmp(info->queue, new_queue) != 0) {
+ char *saved_queue = info->queue;
+ char *saved_path = mystrdup(VSTREAM_PATH(info->stream));
+ VSTRING *new_path = vstring_alloc(100);
+
+ (void) mail_queue_path(new_path, new_queue, info->id);
+ info->queue = mystrdup(new_queue);
+ vstream_control(info->stream, VSTREAM_CTL_PATH, STR(new_path),
+ VSTREAM_CTL_END);
+
+ if (sane_rename(saved_path, STR(new_path)) == 0
+ || (mail_queue_mkdirs(STR(new_path)) == 0
+ && sane_rename(saved_path, STR(new_path)) == 0)) {
+ if (msg_verbose)
+ msg_info("%s: placed in %s queue", info->id, info->queue);
+ } else {
+ msg_fatal("%s: move to %s queue failed: %m", info->id,
+ info->queue);
+ }
+
+ myfree(saved_path);
+ myfree(saved_queue);
+ vstring_free(new_path);
+ }
+}
int mode; /* additional permissions */
};
+#define MAIL_STREAM_CTL_END 0 /* Terminator */
+#define MAIL_STREAM_CTL_QUEUE 1 /* Change queue */
+#define MAIL_STREAM_CTL_CLASS 2 /* Change notification class */
+#define MAIL_STREAM_CTL_SERVICE 3 /* Change notification service */
+#define MAIL_STREAM_CTL_MODE 4 /* Change final queue file mode */
+
extern MAIL_STREAM *mail_stream_file(const char *, const char *, const char *, int);
extern MAIL_STREAM *mail_stream_service(const char *, const char *);
extern MAIL_STREAM *mail_stream_command(const char *);
extern void mail_stream_cleanup(MAIL_STREAM *);
extern int mail_stream_finish(MAIL_STREAM *, VSTRING *);
+extern void mail_stream_ctl(MAIL_STREAM *, int, ...);
/* LICENSE
* Patches change the patchlevel and the release date. Snapshots change the
* release date only.
*/
-#define MAIL_RELEASE_DATE "20050404"
+#define MAIL_RELEASE_DATE "20050413"
#define MAIL_VERSION_NUMBER "2.3"
#define VAR_MAIL_VERSION "mail_version"
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
void lmtp_sasl_initialize(void)
{
+
+ /*
+ * Global callbacks. These have no per-session context.
+ */
+ static sasl_callback_t callbacks[] = {
+ {SASL_CB_LOG, &lmtp_sasl_log, 0},
+ {SASL_CB_LIST_END, 0, 0}
+ };
+
#if SASL_VERSION_MAJOR >= 2 && (SASL_VERSION_MINOR >= 2 \
|| (SASL_VERSION_MINOR == 1 && SASL_VERSION_STEP >= 19))
int sasl_major;
&sasl_major, &sasl_minor,
&sasl_step, (int *) 0);
if (sasl_major != SASL_VERSION_MAJOR
+#if 0
|| sasl_minor != SASL_VERSION_MINOR
- || sasl_step != SASL_VERSION_STEP)
+ || sasl_step != SASL_VERSION_STEP
+#endif
+ )
msg_fatal("incorrect SASL library version. "
- "Postfix was built for version %d.%d.%d, "
+ "Postfix was built with include files from version %d.%d.%d, "
"but the run-time library version is %d.%d.%d",
SASL_VERSION_MAJOR, SASL_VERSION_MINOR, SASL_VERSION_STEP,
sasl_major, sasl_minor, sasl_step);
#endif
- /*
- * Global callbacks. These have no per-session context.
- */
- static sasl_callback_t callbacks[] = {
- {SASL_CB_LOG, &lmtp_sasl_log, 0},
- {SASL_CB_LIST_END, 0, 0}
- };
-
/*
* Sanity check.
*/
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
all: $(PROG) $(LIB)
+$(OBJS) $(LIB_OBJ): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
echo "#"; \
./$(PROG) -d) |egrep -v '^(myhostname|mydomain|mynetworks) ' >$@
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
*
* msg_xxx() does not allocate memory, so it is safe as long as the signal
* handler can't be invoked recursively.
+ *
+ * Assume atomic signal() updates, even when emulated with sigaction(). We
+ * use the in-kernel SIGINT handler address as an atomic variable to
+ * prevent nested postdrop_sig() calls. For this reason, main() must
+ * configure postdrop_sig() as SIGINT handler before other signal
+ * handlers are allowed to invoke postdrop_sig().
*/
- if (postdrop_path) {
- if (remove(postdrop_path))
- msg_warn("uid=%ld: remove %s: %m", (long) getuid(), postdrop_path);
- else if (msg_verbose)
- msg_info("remove %s", postdrop_path);
- postdrop_path = 0;
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
+ (void) signal(SIGQUIT, SIG_IGN);
+ (void) signal(SIGTERM, SIG_IGN);
+ (void) signal(SIGHUP, SIG_IGN);
+ if (postdrop_path) {
+ if (remove(postdrop_path))
+ msg_warn("uid=%ld: remove %s: %m",
+ (long) getuid(), postdrop_path);
+ else if (msg_verbose)
+ msg_info("remove %s", postdrop_path);
+ postdrop_path = 0;
+ }
}
}
static void postdrop_sig(int sig)
{
-
- /*
- * Assume atomic signal() updates, even when emulated with sigaction().
- * We use the in-kernel SIGINT handler address as an atomic variable to
- * prevent nested postdrop_sig() calls. For this reason, main() must
- * configure postdrop_sig() as SIGINT handler before other signal
- * handlers are allowed to invoke postdrop_sig().
- */
- if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
- (void)signal(SIGQUIT, SIG_IGN);
- (void)signal(SIGTERM, SIG_IGN);
- (void)signal(SIGHUP, SIG_IGN);
- postdrop_cleanup();
- /* Future proofing. If you need exit() here then you broke Postfix. */
- _exit(sig);
- }
+ postdrop_cleanup();
+ /* Future proofing. If you need exit() here then you broke Postfix. */
+ _exit(sig);
}
/* main - the main program */
char *attr_name;
char *attr_value;
const char *errstr;
+ char *junk;
/*
* Be consistent with file permissions.
* will not be deleted after we have taken responsibility for delivery.
*/
if (postdrop_path) {
- myfree(postdrop_path);
+ junk = postdrop_path;
postdrop_path = 0;
+ myfree(junk);
}
/*
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
../../libexec/$(PROG): $(PROG)
cp $(PROG) ../../libexec
-SMTPD_CHECK_OBJ = qmqpd_state.o qmqpd_peer.o
-
-qmqpd_token: qmqpd_token.c $(LIBS)
- $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIBS) $(SYSLIBS)
-
-qmqpd_check: qmqpd_check.c $(SMTPD_CHECK_OBJ) $(LIBS)
- mv $@.o junk
- $(CC) $(CFLAGS) -DTEST -o $@ qmqpd_check.c $(SMTPD_CHECK_OBJ) \
- $(LIBS) $(SYSLIBS)
- mv junk $@.o
-
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
void smtp_sasl_initialize(void)
{
+
+ /*
+ * Global callbacks. These have no per-session context.
+ */
+ static sasl_callback_t callbacks[] = {
+ {SASL_CB_LOG, &smtp_sasl_log, 0},
+ {SASL_CB_LIST_END, 0, 0}
+ };
+
#if SASL_VERSION_MAJOR >= 2 && (SASL_VERSION_MINOR >= 2 \
|| (SASL_VERSION_MINOR == 1 && SASL_VERSION_STEP >= 19))
int sasl_major;
&sasl_major, &sasl_minor,
&sasl_step, (int *) 0);
if (sasl_major != SASL_VERSION_MAJOR
+#if 0
|| sasl_minor != SASL_VERSION_MINOR
- || sasl_step != SASL_VERSION_STEP)
+ || sasl_step != SASL_VERSION_STEP
+#endif
+ )
msg_fatal("incorrect SASL library version. "
- "Postfix was built for version %d.%d.%d, "
+ "Postfix was built with include files from version %d.%d.%d, "
"but the run-time library version is %d.%d.%d",
SASL_VERSION_MAJOR, SASL_VERSION_MINOR, SASL_VERSION_STEP,
sasl_major, sasl_minor, sasl_step);
#endif
- /*
- * Global callbacks. These have no per-session context.
- */
- static sasl_callback_t callbacks[] = {
- {SASL_CB_LOG, &smtp_sasl_log, 0},
- {SASL_CB_LIST_END, 0, 0}
- };
-
/*
* Sanity check.
*/
*/
memset(&sec_props, 0L, sizeof(sec_props));
sec_props.min_ssf = 0;
- sec_props.max_ssf = 1; /* don't allow real SASL
+ sec_props.max_ssf = 0; /* don't allow real SASL
* security layer */
sec_props.security_flags = name_mask(sasl_opts_name, smtp_sasl_sec_mask,
sasl_opts_val);
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
if (argc < 3
|| strcasecmp(argv[1].strval, "from:") != 0) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
- smtpd_chat_reply(state, "501 5.5.4 Syntax: MAIL FROM: <address>");
+ smtpd_chat_reply(state, "501 5.5.4 Syntax: MAIL FROM:<address>");
return (-1);
}
if (argc < 3
|| strcasecmp(argv[1].strval, "to:") != 0) {
state->error_mask |= MAIL_ERROR_PROTOCOL;
- smtpd_chat_reply(state, "501 5.5.4 Syntax: RCPT TO: <address>");
+ smtpd_chat_reply(state, "501 5.5.4 Syntax: RCPT TO:<address>");
return (-1);
}
&sasl_major, &sasl_minor,
&sasl_step, (int *) 0);
if (sasl_major != SASL_VERSION_MAJOR
+#if 0
|| sasl_minor != SASL_VERSION_MINOR
- || sasl_step != SASL_VERSION_STEP)
+ || sasl_step != SASL_VERSION_STEP
+#endif
+ )
msg_fatal("incorrect SASL library version. "
- "Postfix was built for version %d.%d.%d, "
+ "Postfix was built with include files from version %d.%d.%d, "
"but the run-time library version is %d.%d.%d",
SASL_VERSION_MAJOR, SASL_VERSION_MINOR, SASL_VERSION_STEP,
sasl_major, sasl_minor, sasl_step);
*/
memset(&sec_props, 0, sizeof(sec_props));
sec_props.min_ssf = 0;
- sec_props.max_ssf = 1; /* don't allow real SASL
+ sec_props.max_ssf = 0; /* don't allow real SASL
* security layer */
sec_props.security_flags = name_mask(sasl_opts_name, smtpd_sasl_mask,
sasl_opts_val);
all: $(PROG)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
all: $(LIB)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
all: $(LIB)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
dict_cdbq->dict.mtime = st.st_mtime;
close_on_exec(fd, CLOSE_ON_EXEC);
+ /*
+ * Warn if the source file is newer than the indexed file, except when
+ * the source file changed only seconds ago.
+ */
+ if (stat(path, &st) == 0
+ && st.st_mtime > dict_cdbq->dict.mtime
+ && st.st_mtime < time((time_t *)0) - 100)
+ msg_warn("database %s is older than source file %s", cdb_path, path);
+
/*
* If undecided about appending a null byte to key and value, choose to
* try both in query mode.
*/
#ifndef SET_H_ERRNO
#define SET_H_ERRNO(err) (h_errno = (err))
+#endif
+
+ /*
+ * Don't mix socket message send/receive calls with socket stream read/write
+ * calls. The fact that you can get away with it only on some stacks implies
+ * that there is no long-term guarantee.
+ */
+#ifndef CAN_WRITE_BEFORE_SENDING_FD
+#define CANT_WRITE_BEFORE_SENDING_FD
#endif
/*
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@
$(PROG): $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+$(OBJS): ../../conf/makedefs.out
+
Makefile: Makefile.in
(cat ../../conf/makedefs.out $?) >$@