2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-31 06:05:37 +00:00

snapshot-19991116

This commit is contained in:
Wietse Venema
1999-11-16 00:00:00 -05:00
parent 6dea8a0d53
commit 406e23a161
27 changed files with 577 additions and 86 deletions

View File

@@ -43,6 +43,9 @@ a process is attempting to do. This is as much information as you
can get without running an interactive debugger program, as described
in the next section.
See the next section on how to automatically attach a program to
a Postfix daemon.
5 - Running daemon programs under an interactive debugger
=========================================================
@@ -68,3 +71,48 @@ Stop and start the Postfix system.
Whenever the suspect daemon process is started, a debugger window
pops up and you can watch in detail what happens.
6 - Unreasonable behavior
=========================
Sometimes the behavior exhibit by Postfix just does not match the
source code. Why can a program deviate from the instructions given
by its author? There are two possibilities.
1 - The compiler has messed up.
2 - The hardware has messed up.
In both cases, the program being executed is not the program that
was supposed to be executed, so anything can happen.
Hardware-related failures happen erratically, and they usually do
not reproduce after power cycling and rebooting the system. There's
little I can do about bad hardware. Be sure to use hardware that
at the very least can detect memory errors. Otherwise, Postfix will
just be a sitting duck waiting to be hit by a bit error. Critical
systems deserve real hardware.
When a compiler messes up, the problem can be reproduced whenever
the resulting program is run. Compiler errors are most likely to
happen in the code optimizer. If a problem is reproducible across
power cycles and system reboots, it can be worthwhile to rebuild
Postfix with optimization disabled, and to see if optimization
makes a difference.
In order to compile Postfix with optimizations turned off:
% make tidy
% make makefiles OPT=
This produces a set of Makefiles that do not request compiler
optomization.
Once the makefiles are set up, build the software:
% make
% su
# make install
And see if the problem reproduces. If the problem goes away, talk
to your vendor.

View File

@@ -3220,6 +3220,23 @@ Apologies for any names omitted.
Feature: permit_auth_destination restriction based on code
by Jesper Skriver @ skriver.dk.
Code cleanup: the transport table now can override local
deliveries. Postfix no longer uses the "empty next-hop
hostname hack" to remember that a destination is local.
Code cleanup: the transport table now can override all
deliveries, including local ones.
19991116
Code cleanup: a new "local_transports" configuration
parameter explicitly lists all transports that deliver
mail locally. The first name listed there is the default
local transport. This is the end of the "empty next-hop
hostname" hack to indicate that a destination is local.
Files: trivial-rewrite/resolve.c, global/local_transport.[hc]
Feature: "postconf -m" shows what lookup table types are
available. Code by Scott Cotton, Internet Consultants
Group, Inc.
Feature: "postconf -e" edits any number of main.cf parameters.
The edit is done on a copy, and the copy is renamed into
the place of the original. File: postconf/postconf.c,
util/readlline.[hc].

View File

@@ -75,6 +75,7 @@ dns_lookup.o: ../include/vstring.h
dns_lookup.o: ../include/vbuf.h
dns_lookup.o: ../include/msg.h
dns_lookup.o: ../include/valid_hostname.h
dns_lookup.o: ../include/stringops.h
dns_lookup.o: dns.h
dns_rr.o: dns_rr.c
dns_rr.o: ../include/sys_defs.h

View File

@@ -247,7 +247,7 @@ static int dns_get_fixed(unsigned char *pos, DNS_FIXED *fixed)
static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
char *rr_name, DNS_FIXED *fixed)
{
char temp[DNS_NAME_LEN];
unsigned char temp[DNS_NAME_LEN];
int data_len;
unsigned pref = 0;
unsigned char *src;

View File

@@ -2,7 +2,8 @@ SHELL = /bin/sh
SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \
debug_peer.c debug_process.c defer.c deliver_completed.c \
deliver_flock.c deliver_pass.c deliver_request.c domain_list.c \
dot_lockfile.c file_id.c header_opts.c is_header.c mail_addr.c \
dot_lockfile.c dot_lockfile_as.c ext_prop.c file_id.c \
header_opts.c is_header.c local_transport.c mail_addr.c \
mail_addr_crunch.c mail_addr_find.c mail_addr_map.c \
mail_command_read.c mail_command_write.c mail_conf.c \
mail_conf_bool.c mail_conf_int.c mail_conf_raw.c mail_conf_str.c \
@@ -16,12 +17,12 @@ SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \
recipient_list.c record.c remove.c resolve_clnt.c resolve_local.c \
rewrite_clnt.c sent.c smtp_stream.c split_addr.c string_list.c \
sys_exits.c timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
tok822_resolve.c tok822_rewrite.c tok822_tree.c ext_prop.c \
dot_lockfile_as.c
tok822_resolve.c tok822_rewrite.c tok822_tree.c
OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
debug_peer.o debug_process.o defer.o deliver_completed.o \
deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
dot_lockfile.o file_id.o header_opts.o is_header.o mail_addr.o \
dot_lockfile.o dot_lockfile_as.o ext_prop.o file_id.o \
header_opts.o is_header.o local_transport.o mail_addr.o \
mail_addr_crunch.o mail_addr_find.o mail_addr_map.o \
mail_command_read.o mail_command_write.o mail_conf.o \
mail_conf_bool.o mail_conf_int.o mail_conf_raw.o mail_conf_str.o \
@@ -35,12 +36,12 @@ OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
recipient_list.o record.o remove.o resolve_clnt.o resolve_local.o \
rewrite_clnt.o sent.o smtp_stream.o split_addr.o string_list.o \
sys_exits.o timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
tok822_resolve.o tok822_rewrite.o tok822_tree.o ext_prop.o \
dot_lockfile_as.o
tok822_resolve.o tok822_rewrite.o tok822_tree.o
HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
dot_lockfile.h file_id.h header_opts.h is_header.h mail_addr.h \
dot_lockfile.h dot_lockfile_as.h ext_prop.h file_id.h \
header_opts.h is_header.h local_transport.h mail_addr.h \
mail_addr_crunch.h mail_addr_find.h mail_addr_map.h mail_conf.h \
mail_copy.h mail_date.h mail_error.h mail_flush.h mail_open_ok.h \
mail_params.h mail_proto.h mail_queue.h mail_run.h mail_scan_dir.h \
@@ -50,7 +51,7 @@ HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
quote_822_local.h rec_streamlf.h rec_type.h recipient_list.h \
record.h resolve_clnt.h resolve_local.h rewrite_clnt.h sent.h \
smtp_stream.h split_addr.h string_list.h sys_exits.h timed_ipc.h \
tok822.h ext_prop.h dot_lockfile_as.h
tok822.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
@@ -62,7 +63,8 @@ LIB = libglobal.a
TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \
mail_addr_map mail_date maps mynetworks mypwd namadr_list \
off_cvt quote_822_local rec2stream recdump resolve_clnt \
resolve_local rewrite_clnt stream2rec string_list tok822_parse
resolve_local rewrite_clnt stream2rec string_list tok822_parse \
local_transport
LIBS = ../lib/libutil.a
LIB_DIR = ../lib
@@ -187,6 +189,11 @@ string_list: $(LIB) $(LIBS)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
mv junk $@.o
local_transport: $(LIB) $(LIBS)
mv $@.o junk
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
mv junk $@.o
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
@@ -361,6 +368,13 @@ header_opts.o: header_opts.h
is_header.o: is_header.c
is_header.o: ../include/sys_defs.h
is_header.o: is_header.h
local_transport.o: local_transport.c
local_transport.o: ../include/sys_defs.h
local_transport.o: ../include/msg.h
local_transport.o: ../include/mymalloc.h
local_transport.o: string_list.h
local_transport.o: mail_params.h
local_transport.o: local_transport.h
mail_addr.o: mail_addr.c
mail_addr.o: ../include/sys_defs.h
mail_addr.o: ../include/stringops.h

View File

@@ -0,0 +1,134 @@
/*++
/* NAME
/* local_transport 3
/* SUMMARY
/* determine if transport delivers locally
/* SYNOPSIS
/* #include <local_transport.h>
/*
/* const char *def_local_transport()
/*
/* int local_transport(transport)
/* const char *transport;
/* DESCRIPTION
/* This module uses the information kept in the "local_transports"
/* configuration parameter, which lists the names of the default
/* local transport followed by zero or more other transports that
/* deliver locally.
/*
/* def_local_transport() returns the name of the default local
/* transport, that is, the first transport name specified with
/* the "local_transports" configuration parameter.
/*
/* local_transport() determines if the named transport is listed
/* in the "local_transports" configuration parameter.
/* SEE ALSO
/* resolve_local(3), see if address resolves locally.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <string.h>
/* Utility library. */
#include <msg.h>
#include <mymalloc.h>
#include <string_list.h>
/* Global library. */
#include <mail_params.h>
#include <local_transport.h>
/* Application-specific */
static STRING_LIST *local_transport_list;
static char *local_transport_name;
/* local_transport_init - initialize lookup table */
static void local_transport_init(void)
{
char *myname = "local_transport_init";
/*
* Sanity check.
*/
if (local_transport_list || local_transport_name)
msg_panic("local_transport_init: duplicate initialization");
/*
* Initialize.
*/
local_transport_list = string_list_init(var_local_transports);
local_transport_name = mystrndup(var_local_transports,
strcspn(var_local_transports, ", \t\r\n"));
/*
* Sanity check.
*/
if (!local_transport(local_transport_name))
msg_panic("%s: unable to intialize", myname);
}
/* def_local_transport - determine default local transport */
const char *def_local_transport(void)
{
/*
* Initialize on the fly.
*/
if (local_transport_list == 0)
local_transport_init();
/*
* Return the first transport listed.
*/
return (local_transport_name);
}
/* local_transport - match address against list of local destinations */
int local_transport(const char *transport)
{
/*
* Initialize on the fly.
*/
if (local_transport_list == 0)
local_transport_init();
/*
* Compare the transport against the list of transports that are listed
* as delivering locally.
*/
return (string_list_match(local_transport_list, transport));
}
#ifdef TEST
#include <vstream.h>
#include <mail_conf.h>
int main(int argc, char **argv)
{
if (argc != 2)
msg_fatal("usage: %s transport", argv[0]);
mail_conf_read();
vstream_printf("%s\n", local_transport(argv[1]) ? "yes" : "no");
vstream_fflush(VSTREAM_OUT);
}
#endif

View File

@@ -0,0 +1,31 @@
#ifndef _LOCAL_TRANSPORT_H_INCLUDED_
#define _LOCAL_TRANSPORT_H_INCLUDED_
/*++
/* NAME
/* local_transport 3h
/* SUMMARY
/* determine if transport delivers locally
/* SYNOPSIS
/* #include <local_transport.h>
/* DESCRIPTION
/* .nf
/*
* External interface.
*/
extern const char *def_local_transport(void);
extern int local_transport(const char *);
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
#endif

View File

@@ -57,6 +57,7 @@
/* time_t var_starttime;
/* int var_ownreq_special;
/* int var_daemon_timeout;
/* char *var_local_transports;
/*
/* void mail_params_init()
/* DESCRIPTION
@@ -161,6 +162,7 @@ int var_soft_bounce;
time_t var_starttime;
int var_ownreq_special;
int var_daemon_timeout;
char *var_local_transports;
/* check_myhostname - lookup hostname and validate */
@@ -261,6 +263,7 @@ void mail_params_init()
VAR_DB_TYPE, DEF_DB_TYPE, &var_db_type, 1, 0,
VAR_HASH_QUEUE_NAMES, DEF_HASH_QUEUE_NAMES, &var_hash_queue_names, 1, 0,
VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim, 0, 1,
VAR_LOCAL_TRANSP, DEF_LOCAL_TRANSP, &var_local_transports, 1, 0,
0,
};
static CONFIG_STR_FN_TABLE function_str_defaults_2[] = {

View File

@@ -80,6 +80,13 @@ extern char *var_myhostname;
#define VAR_MYDOMAIN "mydomain" /* my domain name */
extern char *var_mydomain;
/*
* Transports that deliver locally. Order matters.
*/
#define VAR_LOCAL_TRANSP "local_transports"
#define DEF_LOCAL_TRANSP "local"
extern char *var_local_transports;
/*
* Where to send postmaster copies of bounced mail, and other notices.
*/

View File

@@ -15,7 +15,7 @@
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "Snapshot-19991115"
#define DEF_MAIL_VERSION "Snapshot-19991116"
extern char *var_mail_version;
/* LICENSE

View File

@@ -375,6 +375,7 @@ resolve.o: ../include/resolve_clnt.h
resolve.o: ../include/rewrite_clnt.h
resolve.o: ../include/tok822.h
resolve.o: ../include/mail_params.h
resolve.o: ../include/local_transport.h
resolve.o: local.h
resolve.o: ../include/been_here.h
resolve.o: ../include/deliver_request.h

View File

@@ -62,7 +62,7 @@
#include <rewrite_clnt.h>
#include <tok822.h>
#include <mail_params.h>
#include <resolve_local.h>
#include <local_transport.h>
/* Application-specific. */
@@ -139,7 +139,7 @@ int deliver_resolve_tree(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr
* ugly code to force local recursive alias expansions on a host with no
* authority over the local domain, but that code was just too unclean.
*/
if (resolve_local(STR(reply.nexthop))) {
if (local_transport(STR(reply.transport))) {
status = deliver_recipient(state, usr_attr);
} else {
status = deliver_indirect(state);

View File

@@ -237,7 +237,7 @@ MASTER_SERV *get_master_ent()
* Skip blank lines and comment lines.
*/
do {
if (readlline(buf, master_fp, &master_line) == 0) {
if (readlline(buf, master_fp, &master_line, READLL_STRIPNL) == 0) {
vstring_free(buf);
vstring_free(junk);
return (0);

View File

@@ -164,7 +164,7 @@ static void postalias(char *map_type, char *path_name,
* Add records to the database.
*/
lineno = 0;
while (readlline(line_buffer, source_fp, &lineno)) {
while (readlline(line_buffer, source_fp, &lineno, READLL_STRIPNL)) {
/*
* Skip comments.

View File

@@ -5,21 +5,32 @@
/* Postfix configuration utility
/* SYNOPSIS
/* .fi
/* \fBpostconf\fR [\fB-c \fIconfig_dir\fR] [\fB-d\fR] [\fB-h\fR]
/* [\fB-n\fR] [\fB-v\fR] [\fIparameter ...\fR]
/* \fBpostconf\fR [\fB-dhnv\fR] [\fB-c \fIconfig_dir\fR]
/* [\fIparameter ...\fR]
/*
/* \fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
/* [\fIparameter=value ...\fR]
/* DESCRIPTION
/* The \fBpostconf\fR command prints the actual value of
/* \fIparameter\fR (all known parameters by default), one
/* parameter per line.
/* parameter per line, changes its value, or prints other
/* information about the Postfix mail system.
/*
/* Options:
/* .IP "\fB-c \fIconfig_dir\fR"
/* The \fBmain.cf\fR configuration file is in the named directory.
/* .IP \fB-d\fR
/* Print default parameter settings instead of actual settings.
/* .IP \fB-e\fR
/* Edit the \fBmain.cf\fR configuration file. The file is copied
/* to a temporary file then renamed into place. Parameters and
/* values are specified on the command line. Use quotes in order
/* to protect shell metacharacters and whitespace.
/* .IP \fB-h\fR
/* Show parameter values only, not the ``name = '' label
/* that normally precedes the value.
/* .IP \fB-m\fR
/* List the names of all supported lookup table types.
/* .IP \fB-n\fR
/* Print non-default parameter settings only.
/* .IP \fB-v\fR
@@ -42,10 +53,12 @@
#include <sys_defs.h>
#include <sys/stat.h>
#include <stdio.h> /* rename() */
#include <pwd.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
@@ -66,7 +79,10 @@
#include <dict.h>
#include <safe.h>
#include <mymalloc.h>
#include <line_wrap.h>
#include <argv.h>
#include <split_at.h>
#include <readlline.h>
#include <myflock.h>
/* Global library. */
@@ -78,11 +94,13 @@
#include <mail_addr.h>
/*
* What output we should generate.
* What we're supposed to be doing.
*/
#define SHOW_NONDEF (1<<0) /* show non-default settings */
#define SHOW_DEFS (1<<1) /* show default setting */
#define SHOW_NAME (1<<2) /* show parameter name */
#define SHOW_MAPS (1<<3) /* show map types */
#define EDIT_MAIN (1<<4) /* edit main.cf */
/*
* Lookup table for in-core parameter info.
@@ -214,6 +232,131 @@ static const char *check_mynetworks(void)
return (mynetworks());
}
/* edit_parameters - edit parameter file */
static void edit_parameters(int argc, char **argv)
{
char *config_dir;
char *path;
char *temp;
VSTREAM *src;
VSTREAM *dst;
VSTRING *buf = vstring_alloc(100);
VSTRING *key = vstring_alloc(10);
char *cp;
char *value;
HTABLE *table;
int first = 1;
struct cvalue {
char *value;
int found;
};
struct cvalue *cvalue;
HTABLE_INFO **ht_info;
HTABLE_INFO **ht;
/*
* Store command-line parameters for quick lookup.
*/
table = htable_create(argc);
while ((cp = *argv++) != 0) {
if ((value = split_at(cp, '=')) == 0
|| *(cp += strspn(cp, " \t\r\n")) == 0)
msg_fatal("edit requires \"key = value\" arguments");
cvalue = (struct cvalue *) mymalloc(sizeof(*cvalue));
cvalue->value = value;
cvalue->found = 0;
htable_enter(table, mystrtok(&cp, " \t\r\n"), (char *) cvalue);
}
/*
* XXX Avoid code duplication by better code decomposition.
*/
if (var_config_dir)
myfree(var_config_dir);
var_config_dir = mystrdup((config_dir = safe_getenv(CONF_ENV_PATH)) != 0 ?
config_dir : DEF_CONFIG_DIR); /* XXX */
set_mail_conf_str(VAR_CONFIG_DIR, var_config_dir);
/*
* Open the original file for input.
*/
path = concatenate(var_config_dir, "/", "main.cf", (char *) 0);
if ((src = vstream_fopen(path, O_RDONLY, 0)) == 0)
msg_fatal("open %s for reading: %m", path);
/*
* Open a temp file for the result. We use a fixed name so we don't leave
* behind thrash with random names. Lock the temp file to avoid
* accidents. Truncate the file only after we have an exclusive lock.
*/
temp = concatenate(path, ".tmp", (char *) 0);
if ((dst = vstream_fopen(temp, O_CREAT | O_WRONLY, 0644)) == 0)
msg_fatal("open %s: %m", temp);
if (myflock(vstream_fileno(dst), MYFLOCK_EXCLUSIVE) < 0)
msg_fatal("lock %s: %m", temp);
if (ftruncate(vstream_fileno(dst), 0) < 0)
msg_fatal("truncate %s: %m", temp);
/*
* Copy original file to temp file, while replacing parameters on the
* fly. Issue warnings for names found multiple times.
*/
#define STR(x) vstring_str(x)
while (readlline(buf, src, (int *) 0, READLL_KEEPNL)) {
cp = STR(buf);
if (first) {
first = 0;
if (ISSPACE(*cp))
msg_fatal("%s: file starts with whitespace", path);
}
if (*cp == '#') {
vstream_fputs(STR(buf), dst);
continue;
}
cp += strspn(cp, " \t\r\n");
vstring_strncpy(key, cp, strcspn(cp, " \t\r\n="));
cvalue = (struct cvalue *) htable_find(table, STR(key));
if (cvalue == 0) {
vstream_fputs(STR(buf), dst);
} else {
if (cvalue->found++ == 1)
msg_warn("%s: multiple entries for key %s", path, STR(key));
vstream_fprintf(dst, "%s = %s\n", STR(key), cvalue->value);
}
}
/*
* Generate new entries for parameters that were not found.
*/
for (ht_info = ht = htable_list(table); *ht; ht++) {
cvalue = (struct cvalue *) ht[0]->value;
if (cvalue->found == 0)
vstream_fprintf(dst, "%s = %s\n", ht[0]->key, cvalue->value);
}
myfree((char *) ht_info);
/*
* When all is well, rename the temp file to the original one.
*/
if (vstream_fclose(src))
msg_fatal("read %s: %m", path);
if (vstream_fclose(dst))
msg_fatal("write %s: %m", temp);
if (rename(temp, path) < 0)
msg_fatal("rename %s to %s: %m", temp, path);
/*
* Cleanup.
*/
myfree(path);
myfree(temp);
vstring_free(buf);
vstring_free(key);
htable_free(table, myfree);
}
/* read_parameters - read parameter info from file */
static void read_parameters(void)
@@ -430,6 +573,19 @@ static int comp_names(const void *a, const void *b)
return (strcmp(ap[0]->key, bp[0]->key));
}
/* show_maps - show available maps */
static void show_maps(void)
{
ARGV *maps_argv;
int i;
maps_argv = dict_mapnames();
for (i = 0; i < maps_argv->argc; i++)
vstream_printf("%s\n", maps_argv->argv[i]);
argv_free(maps_argv);
}
/* show_parameters - show parameter info */
static void show_parameters(int mode, char **names)
@@ -470,6 +626,7 @@ int main(int argc, char **argv)
int ch;
int fd;
struct stat st;
int junk;
/*
* To minimize confusion, make sure that the standard file descriptors
@@ -489,44 +646,70 @@ int main(int argc, char **argv)
/*
* Parse JCL.
*/
while ((ch = GETOPT(argc, argv, "c:dhnv")) > 0) {
while ((ch = GETOPT(argc, argv, "c:dehnmv")) > 0) {
switch (ch) {
case 'c':
if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
msg_fatal("out of memory");
break;
case 'd':
if (mode & SHOW_NONDEF)
msg_fatal("specify one of -d and -n");
mode |= SHOW_DEFS;
break;
case 'e':
mode |= EDIT_MAIN;
break;
case 'h':
mode &= ~SHOW_NAME;
break;
case 'm':
mode |= SHOW_MAPS;
break;
case 'n':
if (mode & SHOW_DEFS)
msg_fatal("specify one of -d and -n");
mode |= SHOW_NONDEF;
break;
case 'v':
msg_verbose++;
break;
default:
msg_fatal("usage: %s [-c config_dir] [-d (defaults)] [-h (no names)] [-n (non-defaults)] [-v] name...", argv[0]);
msg_fatal("usage: %s [-c config_dir] [-d (defaults)] [-e (edit)] [-h (no names)] [-m (map types) [-n (non-defaults)] [-v] [name...]", argv[0]);
}
}
/*
* Sanity check.
*/
junk = (mode & (SHOW_DEFS | SHOW_NONDEF | SHOW_MAPS | EDIT_MAIN));
if (junk != 0 && junk != SHOW_DEFS && junk != SHOW_NONDEF
&& junk != SHOW_MAPS && junk != EDIT_MAIN)
msg_fatal("specify one of -d, -e, -n and -m");
/*
* If showing map types, show them and exit
*/
if (mode & SHOW_MAPS) {
show_maps();
}
/*
* Edit main.cf.
*/
if (mode & EDIT_MAIN) {
edit_parameters(argc - optind, argv + optind);
}
/*
* If showing non-default values, read main.cf.
*/
if ((mode & SHOW_DEFS) == 0)
read_parameters();
else {
if ((mode & SHOW_DEFS) == 0)
read_parameters();
/*
* Throw together all parameters and show the asked values.
*/
hash_parameters();
show_parameters(mode, argv + optind);
/*
* Throw together all parameters and show the asked values.
*/
hash_parameters();
show_parameters(mode, argv + optind);
}
vstream_fflush(VSTREAM_OUT);
exit(0);
}

View File

@@ -168,7 +168,7 @@ static void postmap(char *map_type, char *path_name,
* Add records to the database.
*/
lineno = 0;
while (readlline(line_buffer, source_fp, &lineno)) {
while (readlline(line_buffer, source_fp, &lineno, READLL_STRIPNL)) {
/*
* Skip comments.

View File

@@ -110,7 +110,7 @@
#include <deliver_completed.h>
#include <mail_addr_find.h>
#include <opened.h>
#include <resolve_local.h>
#include <local_transport.h>
/* Client stubs. */
@@ -477,7 +477,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
/*
* Bounce mail to non-existent users in virtual domains.
*/
if (!resolve_local(STR(reply.nexthop))
if (!local_transport(STR(reply.transport))
&& qmgr_virtual != 0
&& (at = strrchr(recipient->address, '@')) != 0) {
domain = lowercase(mystrdup(at + 1));
@@ -516,7 +516,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
* job requires knowledge of local aliases. Yuck! I don't want to
* duplicate delivery-agent specific knowledge in the queue manager.
*/
if (resolve_local(STR(reply.nexthop))) {
if (local_transport(STR(reply.transport))) {
vstring_strcpy(reply.nexthop, STR(reply.recipient));
(void) split_at_right(STR(reply.nexthop), '@');
#if 0

View File

@@ -172,6 +172,7 @@ smtpd_check.o: ../include/own_inet_addr.h
smtpd_check.o: ../include/mail_conf.h
smtpd_check.o: ../include/maps.h
smtpd_check.o: ../include/mail_addr_find.h
smtpd_check.o: ../include/local_transport.h
smtpd_check.o: smtpd.h
smtpd_check.o: ../include/mail_stream.h
smtpd_check.o: smtpd_check.h

View File

@@ -275,6 +275,7 @@
#include <mail_conf.h>
#include <maps.h>
#include <mail_addr_find.h>
#include <local_transport.h>
/* Application-specific. */
@@ -712,7 +713,7 @@ static int check_relay_domains(SMTPD_STATE *state, char *recipient,
* Permit if destination is local. XXX This must be generalized for
* per-domain user tables and for non-UNIX local delivery agents.
*/
if (resolve_local(STR(reply.nexthop))
if (local_transport(STR(reply.transport))
|| (domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_OK);
domain += 1;
@@ -751,7 +752,7 @@ static int permit_auth_destination(SMTPD_STATE *state, char *recipient)
* Permit if destination is local. XXX This must be generalized for
* per-domain user tables and for non-UNIX local delivery agents.
*/
if (resolve_local(STR(reply.nexthop))
if (local_transport(STR(reply.transport))
|| (domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_OK);
domain += 1;
@@ -788,7 +789,7 @@ static int reject_unauth_destination(SMTPD_STATE *state, char *recipient)
* Pass if destination is local. XXX This must be generalized for
* per-domain user tables and for non-UNIX local delivery agents.
*/
if (resolve_local(STR(reply.nexthop))
if (local_transport(STR(reply.transport))
|| (domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_DUNNO);
domain += 1;
@@ -890,7 +891,7 @@ static int permit_mx_backup(SMTPD_STATE *unused_state, const char *recipient)
* If the destination is local, it is acceptable, because we are
* supposedly MX for our own address.
*/
if (resolve_local(STR(reply.nexthop))
if (local_transport(STR(reply.transport))
|| (domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_OK);
domain += 1;
@@ -1024,7 +1025,7 @@ static int reject_unknown_address(SMTPD_STATE *state, char *addr,
/*
* Skip local destinations and non-DNS forms.
*/
if (resolve_local(STR(reply.nexthop))
if (local_transport(STR(reply.transport))
|| (domain = strrchr(STR(reply.recipient), '@')) == 0)
return (SMTPD_CHECK_DUNNO);
domain += 1;
@@ -1064,7 +1065,7 @@ static int permit_rcpt_map(char *table, char *reply_name)
return (SMTPD_CHECK_DUNNO);
domain += 1;
if (domain[0] == '#' || domain[0] == '[')
if (!resolve_local(STR(reply.nexthop)))
if (!local_transport(STR(reply.transport)))
return (SMTPD_CHECK_DUNNO);
/*

View File

@@ -72,6 +72,7 @@
#include <mail_conf.h>
#include <quote_822_local.h>
#include <tok822.h>
#include <local_transport.h>
/* Application-specific. */
@@ -151,44 +152,55 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
}
/*
* The transport map, if specified, overrides default routing.
* Make sure the resolved envelope recipient has the user@domain form. If
* no domain was specified in the address, assume the local machine. See
* above for what happens with an empty localpart.
*/
if (*var_transport_maps == 0
|| (tok822_internalize(addr_buf, domain->next, TOK822_STR_DEFL),
transport_lookup(STR(addr_buf), channel, nexthop)) == 0) {
/*
* Non-local delivery. Use the default transport specified in
* var_def_transport. If no default mail relay is specified in
* var_relayhost, forward to the domain's mail exchanger.
*/
if (domain != 0) {
vstring_strcpy(channel, var_def_transport);
if (*var_relayhost)
vstring_strcpy(nexthop, var_relayhost);
else
tok822_internalize(nexthop, domain->next, TOK822_STR_DEFL);
}
/*
* Local delivery. Use the default transport and next-hop hostname.
* If no domain was specified, assume the local machine. See above
* for what happens with an empty localpart.
*/
else {
vstring_strcpy(channel, MAIL_SERVICE_LOCAL);
vstring_strcpy(nexthop, var_myhostname);
if (saved_domain) {
tok822_sub_append(tree, saved_domain);
saved_domain = 0;
} else {
tok822_sub_append(tree, tok822_alloc('@', (char *) 0));
tok822_sub_append(tree, tok822_scan(var_myhostname, (TOK822 **) 0));
}
if (domain == 0) {
if (saved_domain) {
tok822_sub_append(tree, saved_domain);
saved_domain = 0;
} else {
tok822_sub_append(tree, tok822_alloc('@', (char *) 0));
tok822_sub_append(tree, tok822_scan(var_myhostname, (TOK822 **) 0));
}
}
tok822_internalize(nextrcpt, tree, TOK822_STR_DEFL);
/*
* The transport map overrides the default transport and next-hop host
* info that was set up just moments ago. For a long time, it was not
* possible to override routing of mail that resolves locally, because
* Postfix used a zero-length next-hop hostname result to indicate local
* delivery, and transport maps cannot return zero-length hostnames.
*/
if (*var_transport_maps
&& transport_lookup(strrchr(STR(nextrcpt), '@') + 1, channel, nexthop)) {
/* void */ ;
}
/*
* Non-local delivery, presumably. Set up the default remote transport
* specified with var_local_transports. Use the destination's mail
* exchanger unless a default mail relay is specified with var_relayhost.
*/
else if (domain != 0) {
vstring_strcpy(channel, var_def_transport);
if (*var_relayhost)
vstring_strcpy(nexthop, var_relayhost);
else
tok822_internalize(nexthop, domain->next, TOK822_STR_DEFL);
}
/*
* Local delivery. Set up the default local transport and the default
* next-hop hostname.
*/
else {
vstring_strcpy(channel, def_local_transport());
vstring_strcpy(nexthop, var_myhostname);
}
/*
* Clean up.
*/

View File

@@ -394,7 +394,7 @@ void dict_load_fp(const char *dict_name, VSTREAM *fp)
buf = vstring_alloc(100);
lineno = 0;
while (readlline(buf, fp, &lineno)) {
while (readlline(buf, fp, &lineno, READLL_STRIPNL)) {
start = STR(buf);
SKIP(start, member, ISSPACE(*member)); /* find member begin */
if (*member == 0 || *member == '#')

View File

@@ -20,6 +20,7 @@
* Utility library.
*/
#include <vstream.h>
#include <argv.h>
/*
* Generic dictionary interface - in reality, a dictionary extends this
@@ -56,6 +57,11 @@ extern int dict_errno;
#define DICT_SEQ_FUN_FIRST 0 /* set cursor to first record */
#define DICT_SEQ_FUN_NEXT 1 /* set cursor to next record */
/*
* Interface for dictionary types.
*/
extern ARGV *dict_mapnames(void);
/*
* High-level interface, with logical dictionary names.
*/
@@ -96,5 +102,6 @@ extern int dict_changed(void);
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/**INDENT** Error@47: Unmatched #endif */
#endif

View File

@@ -280,6 +280,27 @@ void dict_open_register(const char *type,
htable_enter(dict_open_hash, dp->type, (char *) dp);
}
/* dict_mapnames - return an ARGV of available map_names */
ARGV *dict_mapnames()
{
HTABLE_INFO **ht_info;
HTABLE_INFO **ht;
DICT_OPEN_INFO *dp;
ARGV *mapnames;
if (dict_open_hash == 0)
dict_open_init();
mapnames = argv_alloc(dict_open_hash->used + 1);
for (ht_info = ht = htable_list(dict_open_hash); *ht; ht++) {
dp = (DICT_OPEN_INFO *) ht[0]->value;
argv_add(mapnames, dp->type, ARGV_END);
}
myfree((char *) ht_info);
argv_terminate(mapnames);
return mapnames;
}
#ifdef TEST
/*

View File

@@ -273,7 +273,7 @@ DICT *dict_pcre_open(const char *map, int unused_flags, int dict_flags)
if ((map_fp = vstream_fopen(map, O_RDONLY, 0)) == 0) {
msg_fatal("open %s: %m", map);
}
while (readlline(line_buffer, map_fp, &lineno)) {
while (readlline(line_buffer, map_fp, &lineno, READLL_STRIPNL)) {
if (*vstring_str(line_buffer) == '#') /* Skip comments */
continue;

View File

@@ -373,7 +373,7 @@ DICT *dict_regexp_open(const char *map, int unused_flags, int dict_flags)
if ((map_fp = vstream_fopen(map, O_RDONLY, 0)) == 0) {
msg_fatal("open %s: %m", map);
}
while (readlline(line_buffer, map_fp, &lineno)) {
while (readlline(line_buffer, map_fp, &lineno, READLL_STRIPNL)) {
p = vstring_str(line_buffer);
if (*p == '#') /* Skip comments */

View File

@@ -6,14 +6,16 @@
/* SYNOPSIS
/* #include <readlline.h>
/*
/* VSTRING *readlline(buf, fp, lineno)
/* VSTRING *readlline(buf, fp, lineno, stripnl)
/* VSTRING *buf;
/* VSTREAM *fp;
/* int *lineno;
/* int stripnl;
/* DESCRIPTION
/* readlline() reads one logical line from the named stream.
/* A line that starts with whitespace is a continuation of
/* the previous line. The newline between continued lines
/* the previous line. When the stripnl argument is non-zero,
/* the newline between continued lines
/* is deleted from the input. The result value is the input
/* buffer argument or a null pointer when no input is found.
/*
@@ -25,6 +27,9 @@
/* .IP lineno
/* A null pointer, or a pointer to an integer that is incremented
/* after reading a newline.
/* .IP stripnl
/* Non-zero to strip newlines. readlline.h provides the symbolic
/* constants READLL_STRIPNL and READLL_KEEPNL for convenience.
/* LICENSE
/* .ad
/* .fi
@@ -48,7 +53,7 @@
/* readlline - read one logical line */
VSTRING *readlline(VSTRING *buf, VSTREAM *fp, int *lineno)
VSTRING *readlline(VSTRING *buf, VSTREAM *fp, int *lineno, int stripnl)
{
int ch;
int next;
@@ -59,6 +64,8 @@ VSTRING *readlline(VSTRING *buf, VSTREAM *fp, int *lineno)
VSTRING_RESET(buf);
while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
if (ch == '\n') {
if (stripnl == 0)
VSTRING_ADDCH(buf, ch);
if (lineno)
*lineno += 1;
if ((next = VSTREAM_GETC(fp)) == ' ' || next == '\t') {

View File

@@ -20,7 +20,10 @@
/*
* External interface.
*/
extern VSTRING *readlline(VSTRING *, VSTREAM *, int *);
extern VSTRING *readlline(VSTRING *, VSTREAM *, int *, int);
#define READLL_STRIPNL 1
#define READLL_KEEPNL 0
/* LICENSE
/* .ad