/*
#ident	"@(#)smail/src:RELEASE-3_2_0_120:default.c,v 1.79 2004/08/17 19:17:35 woods Exp"
 */

/*
 *    Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
 *    Copyright (C) 1992  Ronald S. Karr
 * 
 * See the file COPYING, distributed with smail, for restriction
 * and warranty information.
 */

/*
 * default:
 *	default values to be used in the event that no other info is given
 *
 * Items are placed in this file ONLY if they represent the default behavior
 * of smail and it's utilities, and ONLY if the default behavior can be changed
 * by `config.h' or the `startup' file.
 */

#include "defs.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <stdio.h>

#ifdef __STDC__
# include <stdarg.h>
#else
# include <varargs.h>
#endif

#include "smail.h"
#include "config.h"
#include "main.h"
#include "parse.h"
#include "addr.h"
#include "direct.h"
#include "route.h"
#include "alloc.h"
#include "list.h"
#include "smailstring.h"
#include "dys.h"
#include "smailsock.h"
#include "drivertab.h"
#include "transport.h"
#if defined(HAVE_BIND) && defined(USE_BIND)
# include "bindlib.h"
#endif
#ifndef DEPEND
# include "extern.h"
#endif
#include "directors/include.h"
#include "directors/aliasfile.h"
#include "directors/fwdfile.h"
#include "directors/user.h"
#include "directors/smartuser.h"
#include "routers/gethost.h"
#include "routers/uuname.h"
#include "routers/pathalias.h"
#include "routers/smarthost.h"
#include "routers/reroute.h"
#include "routers/rewrite.h"
#include "transports/pipe.h"
#include "transports/appendfile.h"
#include "transports/tcpsmtp.h"
#include "transports/smtplib.h"
#include "smailport.h"

/*
 * SUCC is set to point to the previously defined director, router or
 * transport, and is redefined after each new definition, to make it
 * simpler to optionally include links in the various configuration
 * chains.
 *
 * NOTE:  directors, routers and transports are listed in reverse order.
 *	  This causes `forward' links to work without declaring them in
 *	  advance.
 */


/*
 * START OF DIRECTOR DEFINITION SECTION
 */

#undef SUCC
#define SUCC	NULL			/* end of director list */

#ifdef SMARTUSER_DIRECTOR_DRV_NM
# ifdef SMART_USER
static struct smartuser_private smartuser_director_priv = {
    SMART_USER,				/* address for unknown users */
    NULL,				/* no transport */
    NULL,				/* prefix */
    NULL,				/* suffix */
    NULL,				/* internal use only */
};

static struct director smartuser_director = {
    "smart_user",			/* mailing lists */
    SMARTUSER_DIRECTOR_DRV_NM,		/* use the smartuser driver */
    SUCC,				/* point to next director */
    SMARTUSER_WELLFORMED,		/* match only well-formed addresses */
    NULL,				/* no address owner */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    (char *) &smartuser_director_priv,	/* local private configuration */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
#  undef SUCC
#  define SUCC (&smartuser_director)	/* setup for forward link */
# endif	/* SMART_USER */

/*
 * OWNER DIRECTOR:
 *
 * This matches users on the local host with a prefix of "owner-" and rewrites
 * them to go to the postmaster.  It comes second last so that aliases can be
 * set to forward specific owner-* addresses to other addresses.
 *
 * Note that this is only a last-ditch catch-all since normally owner addresses
 * which cannot be verified will default to "postmaster" anyway.
 */
static struct smartuser_private owner_director_priv = {
    "postmaster",			/* address for unknown owners */
    NULL,				/* no transport */
    "owner-",				/* prefix */
    NULL,				/* suffix */
    NULL,				/* internal use only */
};

static struct director owner_director = {
    "owner",				/* owners */
    SMARTUSER_DIRECTOR_DRV_NM,		/* use the smartuser driver */
    SUCC,				/* point to next director */
    SENDER_OKAY, 			/* allow expansion to match sender */
    "postmaster",			/* errors go to the postmaster */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    (char *) &owner_director_priv,	/* local private configuration */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
# undef SUCC
# define SUCC (&owner_director)		/* setup for forward link */
#endif /* SMARTUSER_DIRECTOR_DRV_NM */


#ifdef USER_DIRECTOR_DRV_NM
/*
 * REAL_USER DIRECTOR:
 *
 * This matches users on the local host, with a prefix of "real-" and
 * associates them with the transport that appends to user mailbox
 * files.
 *
 * This director allows a user's mailbox to specified literally with
 * a form that won't go through aliasing or forwarding (generally).
 * This is useful in scenarios that cannot easily be solved without
 * mail loops, such as people who wish all mail to be forwarded to
 * multiple machines.
 */
static struct user_private real_user_director_priv = {
#if defined(USE_CYRUS_IMAPD)
    "cyrus_deliver",			/* use the Cyrus IMAPd "deliver" transport */
#else
    "local",				/* use the local transport */
#endif
    "real-",				/* prefix */
    NULL,				/* suffix */
#ifdef HAVE_FGETPWENT
    NULL,				/* password file (use system) */
#endif
};

static struct director real_user_director = {
    "real_user",			/* directing to real local users */
    USER_DIRECTOR_DRV_NM,		/* use the user driver */
    SUCC,				/* point to next director */
    0,					/* no flags */
    NULL,				/* no address owner */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    (char *) &real_user_director_priv,	/* local private configuration */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
#undef SUCC
#define SUCC (&real_user_director)	/* setup for forward link */


#if defined(USE_CYRUS_IMAPD)

# if !defined(NO_CYRUS_USER_WITH_MBOX)
/*
 * USER-WITH-MBOX DIRECTOR:
 *
 * This matches users on the local host, with a suffix mailbox appended to
 * their address, and associates them with the Cyrus IMAPd transport that
 * delivers directly to the user's sub-mailbox folders in Cyrus IMAP.
 *
 * This director must come after (i.e. before in this file) the user_inbox
 * director which matches the plain username.
 */
static struct user_private user_with_mbox_director_priv = {
    "cyrus_deliver",			/* use the Cyrus IMAPd "deliver" transport */
    NULL,				/* no prefix */
#  ifdef USE_OBSOLETE_BASIC_RE
    "[-+]\\(.*\\)",			/* mailbox */
#  else
    "[-+](.*)",				/* mailbox */
#  endif
#  ifdef HAVE_FGETPWENT
    NULL,				/* password file (use system) */
#  endif
};

static struct director user_with_mbox_director = {
    "user_with_mbox",			/* directing to Cyrus users with suffix mbox */
    USER_DIRECTOR_DRV_NM,		/* use the user driver */
    SUCC,				/* point to next director */
    0,					/* no flags */
    NULL,				/* no address owner */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    (char *) &user_with_mbox_director_priv, /* local private configuration */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
#  undef SUCC
#  define SUCC (&user_with_mbox_director)	/* setup for forward link */
# endif /* !NO_CYRUS_USER_WITH_MBOX */

/*
 * USER_INBOX DIRECTOR:
 *
 * This matches users on the local host and associates them with the Cyrus
 * IMAPd transport that delivers to the user's default INBOX folder in Cyrus
 * IMAP.
 */
static struct user_private user_inbox_director_priv = {
    "cyrus_deliver",			/* use the Cyrus IMAPd "deliver" transport */
    NULL,				/* no prefix */
    NULL,				/* no suffix */
# ifdef HAVE_FGETPWENT
    NULL,				/* password file (use system) */
# endif
};

static struct director user_inbox_director = {
    "user_inbox",			/* directing to Cyrus INBOX */
    USER_DIRECTOR_DRV_NM,		/* use the user driver */
    SUCC,				/* point to next director */
    0,					/* no flags */
    NULL,				/* no address owner */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    (char *) &user_inbox_director_priv,	/* local private configuration */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
# undef SUCC
# define SUCC (&user_inbox_director)	/* setup for forward link */

/*
 * NOQUOTA_USER DIRECTOR:
 *
 * This matches users on the local host with a secret passphrase prefix and
 * associates them with the Cyrus IMAPd noquota transport that delivers to the
 * user's default INBOX folder in Cyrus IMAP without heed to quotas (i.e. with
 * '-q').
 */
static struct user_private noquota_user_director_priv = {
    "cyrus_deliver_noquota",		/* use the Cyrus noquota transport */
    "${cyrus_noquota_passphrase}-",	/* secret passphrase prefix */
    NULL,				/* no suffix */
# ifdef HAVE_FGETPWENT
    NULL,				/* password file (use system) */
# endif
};

static struct director noquota_user_director = {
    "noquota_user",			/* directing to Cyrus INBOX */
    USER_DIRECTOR_DRV_NM,		/* use the user driver */
    SUCC,				/* point to next director */
    0,					/* no flags */
    NULL,				/* no address owner */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    (char *) &noquota_user_director_priv, /* local private configuration */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
# undef SUCC
# define SUCC (&noquota_user_director)	/* setup for forward link */

# ifdef ALIASFILE_DIRECTOR_DRV_NM
static struct aliasfile_private over_quota_director_priv = {
    OVER_QUOTA_FILE,			/* this is set in config.h */
    OVER_QUOTA_PROTO,			/* file access method */
    0002,				/* should not be globally writable */
    NULL,				/* no ownership restriction */
    NULL,				/* no group ownership restriction */
    0,					/* no retries */
    0,					/* two second intervals for retries */
    0,					/* temp - addr flags bit mask */
    NULL,				/* temp - open database */
    NULL,				/* temp - error from open */
};

static struct director over_quota_director = {
    "over_quota",			/* handle list of over-quota mailboxes */
    ALIASFILE_DIRECTOR_DRV_NM,		/* use the aliasfile driver */
    SUCC,				/* point to next director */
    ALIAS_OPTIONAL,			/* the OVER_QUOTA_FILE is optional */
    NULL,				/* no default owner */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    (char *) &over_quota_director_priv,	/* local private configuration */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
#  undef SUCC
#  define SUCC (&over_quota_director)	/* setup for forward link */
# endif	/* ALIASFILE_DIRECTOR_DRV_NM */

# if !defined(NO_LOCAL_USER)
static struct user_private local_user_director_priv = {
    "local",				/* use the local transport */
    "local-",				/* prefix */
    NULL,				/* no suffix */
#  ifdef HAVE_FGETPWENT
    NULL,				/* password file (use system) */
#  endif
};

static struct director local_user_director = {
    "local_user",			/* directing to local users */
    USER_DIRECTOR_DRV_NM,		/* use the user driver */
    SUCC,				/* point to next director */
    0,					/* no flags */
    NULL,				/* no address owner */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    (char *) &local_user_director_priv,	/* local private configuration */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
#  undef SUCC
#  define SUCC (&local_user_director)	/* setup for forward link */
# endif	/* !NO_LOCAL_USER */

#else /* !USE_CYRUS_IMAPD */

/*
 * USER DIRECTOR:
 *
 * This matches users on the local host and associates them with the local
 * transport which appends to the user's mailbox spool file in the system mail
 * spool directory.
 */
static struct user_private user_director_priv = {
    "local",				/* use the local transport */
    NULL,				/* no prefix */
    NULL,				/* no suffix */
# ifdef HAVE_FGETPWENT
    NULL,				/* password file (use system) */
# endif
};

static struct director user_director = {
    "user",				/* directing to local users */
    USER_DIRECTOR_DRV_NM,		/* use the user driver */
    SUCC,				/* point to next director */
    0,					/* no flags */
    NULL,				/* no address owner */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    (char *) &user_director_priv,	/* local private configuration */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
# undef SUCC
# define SUCC (&user_director)		/* setup for forward link */

#endif /* !USE_CYRUS_IMAPD */

#endif /* USER_DIRECTOR_DRV_NM */

#if defined(FORWARDTO_FILE) && defined(FORWARDFILE_DIRECTOR_DRV_NM)
/*
 * FORWARDTO DIRECTOR:
 *
 * This looks for forwarding information in user mailbox files, for
 * mailbox files that begin with "Forward to [addr list ...]".
 */
static struct forwardfile_private forwardto_director_priv = {
    FORWARDTO_FILE,			/* Where to find forward to files */
#if !defined(UNIX_SYS5) && !defined(UNIX_SUN_OS_4_1)
    0002,				/* mail group must write in SysV */
#else
    0022,				/* should not be very writable */
#endif
#ifdef FORWARDTO_CAUTION
    FORWARDTO_CAUTION,
#else
    "0-99:uucp:daemon",			/* be cautious of some user's files */
#endif
    NULL,				/* nothing is `unsecure' */
    "root",				/* can be owned by root */
    NULL,				/* no group ownership restriction */
    NULL,				/* no prefix */
    NULL,				/* no suffix */
};

static struct director forwardto_director = {
    "forwardto",			/* directing through alias file */
    FORWARDFILE_DIRECTOR_DRV_NM,	/* use the forwardfile driver */
    SUCC,				/* point to next director */
    /*
     * secure source of addresses, owner should be the user, use
     * "nobody" for addresses returned by unsecure forward files
     */
    FWD_CHECKOWNER |
	FWD_FORWARDTO |
	NOBODY_DIRECTOR |
	SENDER_OKAY,
    "Postmaster",			/* errors go to the postmaster */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    (char *) &forwardto_director_priv,	/* forwardto private configuration */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
#undef SUCC
#define SUCC (&forwardto_director)	/* setup for forward link */
#endif	/* FORWARDTO_FILE */


#if !defined(NO_DOTFORWARD) && defined(FORWARDFILE_DIRECTOR_DRV_NM)
/*
 * DOTFORWARD DIRECTOR:
 *
 * This looks for .forward files in a user's home directory.
 */
static struct forwardfile_private dotforward_director_priv = {
    "~/.forward",			/* .forward in home directories */
    0002,				/* should not be globally writable */
#ifdef DOTFWARD_CAUTION
    DOTFORWARD_CAUTION,
#else
    "0-99:uucp:daemon",			/* be cautious of some forward file */
#endif
    /* remotely accessible directories are very unsecure */
    REMOTE_HOMES,
    "root",				/* can also be owned by root */
    NULL,				/* no group ownership restriction */
    NULL,				/* no prefix */
    NULL,				/* no suffix */
};

static struct director dotforward_director = {
    "dotforward",			/* directing through alias file */
    FORWARDFILE_DIRECTOR_DRV_NM,	/* use the forwardfile driver */
    SUCC,				/* point to next director */
    /*
     * secure source of addresses, file owner should be the user, use "nobody"
     * for addresses returned by unsecure forward files
     */
    FWD_CHECKOWNER |
	NOBODY_DIRECTOR |
	SENDER_OKAY,
    "real-$user",			/* address errors go to user */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    (char *) &dotforward_director_priv,	/* dotforward private configuration */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
#undef SUCC
#define SUCC (&dotforward_director)	/* setup for forward link */
#endif /* !NO_DOTFORWARD */


#if defined(LIST_FILENAME) && defined(FORWARDFILE_DIRECTOR_DRV_NM)
/*
 * LIST DIRECTOR:
 *
 * This matches mailing lists files stored in the defined mailing list
 * directory.
 */
static struct forwardfile_private list_director_priv = {
    LIST_FILENAME,			/* file in mailing list directory */
    0,					/* don't worry about file modes */
    NULL,				/* no specific caution warnings */
    NULL,				/* no specific unsecure areas */
    NULL,				/* anybody can own these */
    NULL,				/* any group can own these */
    NULL,				/* no prefix */
    NULL,				/* no suffix */
};

static struct director list_director = {
    "lists",				/* mailing lists */
    FORWARDFILE_DIRECTOR_DRV_NM,	/* use the forwardfile driver */
    SUCC,				/* point to next director */
    /*
     * set only the caution flag and not the nobody flag to disallow any files
     * or pipes in the addresses returned by this director.
     */
#if !defined(LISTS_REMOVE_SENDER)
    SENDER_OKAY |
#endif
	CAUTION_DIRECTOR,
    LIST_OWNER,				/* normal address owner owners */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    (char *) &list_director_priv,	/* local private configuration */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
# undef SUCC
# define SUCC (&list_director)		/* setup for forward link */
#endif	/* LIST_FILENAME */


#if defined(ALIASES_FILE) && defined(ALIASFILE_DIRECTOR_DRV_NM)
/*
 * ALIASFILE DIRECTOR:
 *
 * The name of the alias file and its access method type is defined in
 * config.h, if an aliasfile is configured.
 */
static struct aliasfile_private aliases_director_priv = {
    ALIASES_FILE,			/* this is set in config.h */
    ALIASES_PROTO,			/* file access method */
    0002,				/* should not be globally writable */
    NULL,				/* no ownership restriction */
    NULL,				/* no group ownership restriction */
#ifdef	HAVE_RENAME
    /*
     * if we have an atomic rename call, retries should not be required
     * since the file should always exist, even when being rebuilt
     *
     * if the file is not found, the aliases director is ignored.
     */
    0,					/* no retries */
#else	/* HAVE_RENAME */
    /*
     * without an atomic rename call, there will be short periods
     * of time when the file does not exist, while it is being
     * rebuilt
     */
    2,					/* two retries on open */
#endif	/* HAVE_RENAME */
    10,					/* two second intervals for retries */
    0,					/* temp - addr flags bit mask */
    NULL,				/* temp - open database */
    NULL,				/* temp - error from open */
};

static struct director aliases_director = {
    "aliases",				/* directing through alias file */
    ALIASFILE_DIRECTOR_DRV_NM,		/* use the aliasfile driver */
    SUCC,				/* point to next director */
#if !defined(ALIASES_REMOVE_SENDER)
    SENDER_OKAY |
#endif
#ifdef ALIASES_OPTIONAL
	ALIAS_OPTIONAL |
#endif
#ifdef ALIASES_TRYAGAIN
	ALIAS_TRYAGAIN |
#endif
	NOBODY_DIRECTOR,		/* secure source of addresses */
    ALIASES_OWNER,			/* default owner */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    (char *) &aliases_director_priv,	/* aliases private configuration */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
#undef SUCC
#define SUCC (&aliases_director)	/* setup for forward link */
#endif	/* ALIASES_FILE */


#if (!defined(NO_DOTFORWARD) || defined(FORWARDTO_FILE)) && defined(FORWARDINCLUDE_DIRECTOR_DRV_NM)
/*
 * FORWARDINCLUDE DIRECTOR:
 *
 * This is configured only if the dotforward or forwardto directors
 * are also configured in.  It is setup to copy security and ownership
 * restrictions from the dotforward/forwardto directors.
 */
static struct director forwardinclude_director = {
    "forwardinclude",			/* directing through :include: files from dotforward */
    FORWARDINCLUDE_DIRECTOR_DRV_NM,	/* use the forwardinclude driver */
    SUCC,				/* point to next director */
    COPY_SECURE | COPY_OWNERS |		/* restrictions from forward file */
	NOBODY_DIRECTOR,		/*  */
    NULL,				/* no address owner */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    NULL,				/* no private data */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
#undef SUCC
#define SUCC (&forwardinclude_director)	/* setup for forward link */
#endif	/* !defined(NO_DOTFORWARD) || defined(FORWARDTO_FILE) */


#if defined(ALIASES_FILE) && defined(ALIASINCLUDE_DIRECTOR_DRV_NM)
/*
 * ALIASINCLUDE DIRECTOR:
 *
 * This is configured only if the aliases director is also configured
 * in.  It is setup to copy security and ownership restrictions from
 * the aliases file director.
 */
static struct director aliasinclude_director = {
    "aliasinclude",			/* directing through :include: files from aliases */
    ALIASINCLUDE_DIRECTOR_DRV_NM,	/* use the aliasinclude driver */
    SUCC,				/* point to next director */
    COPY_SECURE | COPY_OWNERS |		/* restrictions from aliases */
	NOBODY_DIRECTOR,		/*  */
    ALIASES_OWNER,			/* default owner */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    NULL,				/* no private data */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
# undef SUCC
# define SUCC (&aliasinclude_director)	/* setup for forward link */
#endif	/* ALIASES_FILE */

#if defined(ERROR_DIRECTOR_NM) && defined(ERROR_DIRECTOR_DRV_NM)
/*
 * ERROR DIRECTOR:
 */
static struct director error_director = {
    ERROR_DIRECTOR_NM,			/* matching ":fail:" and ":defer:" */
    ERROR_DIRECTOR_DRV_NM,		/* use the error driver */
    SUCC,				/* point to next director */
    0,					/* no flags */
    NULL,				/* default owner */
    NULL,				/* no default user */
    NULL,				/* no default group */
    NULL,				/* no default home director */
    NULL,				/* no specific domains */
    NULL,				/* no explicit user */
    NULL,				/* no explicit group */
    NULL,				/* no explicit home directory */
    NULL,				/* no private data */
    0,					/* cache - default uid */
    0,					/* cache - default gid */
    NULL,				/* cache - expanded default home */
    0,					/* cache - set uid */
    0,					/* cache - set gid */
    NULL,				/* cache - expanded set home */
};
# undef SUCC
# define SUCC (&error_director)		/* setup for forward link */
#endif /* ERROR_DIRECTOR*_NM */

/* point to the first director */
struct director *directors = SUCC;


/*
 * START OF ROUTER DEFINITION SECTION
 */

#undef SUCC
#define SUCC	NULL			/* end of router list */

#ifdef USE_INTERNAL_METHOD_TABLE	/* not defined by default */
/*
 * A hard-coded built-in method table used by the smart_host, uucp_neighbours,
 * paths, rewrite, reroute, and force_paths routers.
 */
static struct method method_table[] = {
/* you could list sites you wish to poll on demand, for example:
 *  { "ihnp4",	-1, -1, "demand" },
 *  { "mcvax",	-1, -1, "demand" },
 * if some sites require a different transport, make a transport
 * entry and give its name instead of "demand" or "uux".
 *
 * The demand transport calls uux without the -r flag so that uucico is
 * started immediately to perform delivery.
 *
 * The uux transport calls uux with the -r flag, so that requests are
 * just queued, uucico is not started to perform delivery immediately.
 */
    { "*/*-C",	-1, -1, "demand" },	/* use "demand" for high-grade messages */
    { "*",	-1, -1, "uux" },	/* use "uux" for all other hosts */
    { NULL,	-1, -1, 0},		/* end of first table */
};
# define METHOD_TABLE method_table

#else	/* not USE_INTERNAL_METHOD_TABLE */

# define METHOD_TABLE NULL		/* default definition as per config.h */

#endif	/* not USE_INTERNAL_METHOD_TABLE */


#if defined(UUNAME_COMMAND) && defined(UUNAME_TRANSPORT) && defined(UUNAME_ROUTER_DRV_NM)
/*
 * UUNAME ROUTER:
 *
 * The name for the uuname or a uuname-style program is configured in
 * config.h, if one is to be used for finding neighboring host names.
 */
static struct uuname_private uuname_router_priv = {
    UUNAME_COMMAND,			/* cmd attribute */
    "uucp",				/* default domains */
    NULL,				/* required domains */
# ifdef UUCP_SYSTEM_FILE
    UUCP_SYSTEM_FILE,			/* file to stat for changes */
# else
    NULL,
# endif
    NULL,				/* internal - cached output from cmd */
    NULL,				/* internal - end of cached output */
    NULL,				/* internal - processing error */
    0,					/* internal - st_ino from stat */
    0,					/* internal - st_mtime from stat */
};

static struct router uuname_router = {
    "uucp_neighbors",			/* routing through uuname output */
    UUNAME_ROUTER_DRV_NM,		/* use the uuname driver */
    SUCC,				/* point to next router */
    0,					/* no options turned on */
    METHOD_TABLE,			/* use method table from pathalias */
    UUNAME_TRANSPORT,			/* default transport */
    (char *) &uuname_router_priv,	/* uuname private configuration */
};
# undef SUCC
# define SUCC (&uuname_router)		/* setup for forward link */
#endif	/* UUNAME_COMMAND && UUNAME_TRANSPORT */


#if defined(PATHS_FILE) && defined(PATHALIAS_ROUTER_DRV_NM)
/*
 * PATHALIAS ROUTER:
 *
 * The name of the paths file and the access method type is defined in
 * config.h, if a pathalias database is configured.
 */
static struct pathalias_private pathalias_router_priv = {
    PATHS_FILE,				/* file attribute */
    PATHS_PROTO,			/* file access method */
    "uucp",				/* default domain names */
    NULL,				/* no required domain names */
# ifdef	HAVE_RENAME
    /*
     * if we have an atomic rename call, retries should not be required
     * since the file should always exist, even when being rebuilt
     *
     * if the file is not found, the pathalias director is ignored.
     */
    0,					/* no retries */
# else	/* HAVE_RENAME */
    /*
     * without an atomic rename call, there will be short periods
     * of time when the file does not exist, while it is being
     * rebuilt
     */
    2,					/* two retries on open */
# endif	/* HAVE_RENAME */
    10,					/* ten second intervals for retries */
    NULL,				/* internal - open database */
    NULL,				/* internal - error text from open */
};

static struct router pathalias_router = {
    "paths",				/* routing through pathalias file */
    PATHALIAS_ROUTER_DRV_NM,		/* use the pathalias driver */
    SUCC,				/* point to next router */
# ifdef PATHS_OPTIONAL
    PA_OPTIONAL |			/* the paths file is optional */
# endif
# ifdef PATHS_TRYAGAIN
	PA_TRYAGAIN |			/* defer address on open failure */
# endif
	PA_REOPEN,			/* always reopen database to search */
    METHOD_TABLE,			/* use method table to find tport */
    PATHS_TRANSPORT,			/* default transport */
    (char *) &pathalias_router_priv,	/* pathalias private configuration */
};
# undef SUCC
# define SUCC (&pathalias_router)	/* setup for forward link */
#endif	/* PATHS_FILE */


#if defined(USE_GETHOSTBYNAME) && defined(GETHOSTBYNAME_ROUTER_DRV_NM)
/*
 * GETHOSTBYNAME ROUTER:
 *
 * Define a fairly generic interface to gethostbyname(3N)
 */

static struct gethostbyname_private inet_hosts_router_priv = {
    NULL,				/* no optional domain names */
    NULL,				/* no required domain names */
};

static struct router inet_hosts_router = {
    "inet_hosts",			/* match hosts on an IP network */
    GETHOSTBYNAME_ROUTER_DRV_NM,	/* use the gethostbyname driver */
    SUCC,				/* point to next router */
    0,					/* no options turned on */
    (struct method *)NULL,		/* no method table */
    GETHOSTBYNAME_TRANSPORT,		/* default transport */
    (char *) &inet_hosts_router_priv,	/* private configuration */
};
# undef SUCC
# define SUCC (&inet_hosts_router)	/* setup for forward link */
#endif	/* USE_GETHOSTBYNAME */


#if defined(HAVE_BIND) && defined(USE_BIND) && defined(BIND_ROUTER_DRV_NM)
/*
 * BIND ROUTER:
 *
 * Define a fairly generic interface to resolver(3N)
 */

static struct bindlib_private bind_hosts_router_priv = BIND_TEMPLATE_ATTRIBUTES;

static struct router bind_hosts_router = {
    "bind_hosts",			/* match hosts on an IP network */
    BIND_ROUTER_DRV_NM,			/* use the bind driver */
    SUCC,				/* point to next router */
    USE_ALWAYS |			/* doc-only: the DNS is authoritative */
    BIND_DEFER_NO_CONN |		/* defer if connection not successful */
	BIND_MX_ONLY |			/* only match MX'ed hosts (see gethostbyname) */
	BIND_DOMAIN_REQUIRED,		/* don't match un-qualified names */
    (struct method *)NULL,		/* no method table */
    BIND_TRANSPORT,			/* default transport */
    (char *) &bind_hosts_router_priv,	/* private configuration */
};
# undef SUCC
# define SUCC (&bind_hosts_router)	/* setup for forward link */
#endif	/* USE_BIND, etc. */


#if defined(USE_GETHOSTBYADDR) && defined(GETHOSTBYADDR_ROUTER_DRV_NM)
/*
 * GETHOSTBYADDR ROUTER:
 *
 * Define a fairly generic interface to gethostbyaddr(3N) and the
 * inet_addr(3N) routines.
 */

static struct router inet_addrs_router = {
    "inet_addrs",			/* match IP addrs on an IP network */
    GETHOSTBYADDR_ROUTER_DRV_NM,	/* use the gethostbyaddr driver */
    SUCC,				/* point to next router */
    USE_ALWAYS |			/* no need to check further if match */
	GETHOST_FAIL_IFERR |
	GETHOST_CHECK_LOCAL,		/* fail_if_error + check_local */
    (struct method *)NULL,		/* no method table */
    GETHOSTBYADDR_TRANSPORT,		/* default transport */
    (char *)NULL,			/* no private configuration */
};
# undef SUCC
# define SUCC (&inet_addrs_router)	/* setup for forward link */
#endif	/* USE_GETHOSTBYADDR */


#if defined(EXPERIMENTAL_REROUTER) && defined(REROUTE_ROUTER_DRV_NM)

/*
 * REROUTE ROUTER:
 *
 * By default, this router is used only to collaps bang path addresses
 * in bounce mails.  This has to be the first router in the calling
 * sequence.
 */
static struct reroute_private reroute_router_priv = {
    NULL,				/* no file attribute */
    NULL,				/* no file access method */
    NULL,				/* no default domain names */
    NULL,				/* no required domain names */
    0,					/* no retries */
    0,					/* no retries */
    NULL,				/* internal - open database */
    NULL,				/* internal - error text from open */
};

static struct router reroute_router = {
    "reroute",				/* routing through rerouter */
    REROUTE_ROUTER_DRV_NM,		/* use the reroute driver */
    SUCC,				/* point to next router */
    RR_MATCHLOCAL | RR_BOUNCEONLY,	/* default options */
    METHOD_TABLE,			/* use method table to find tport */
    PATHS_TRANSPORT,			/* default transport */
    (char *) &reroute_router_priv,	/* reroute private configuration */
};
# undef SUCC
# define SUCC (&reroute_router)		/* setup for forward link */

#endif	/* EXPERIMENTAL_REROUTER */


#if defined(REWRITE_FILE) && defined(REWRITE_ROUTER_DRV_NM)
/*
 * REWRITE ROUTER:
 *
 * The name of the rewrite file and the access method type is
 * defined in config.h, if a rewrite database is configured.
 */

static struct rewrite_private rewrite_router_priv = {
    REWRITE_FILE,			/* file attribute */
    REWRITE_PROTO,			/* file access method */
    NULL,				/* default domain names */
    NULL,				/* no required domain names */
# ifdef	HAVE_RENAME
    /*
     * if we have an atomic rename call, retries should not be required
     * since the file should always exist, even when being rebuilt
     *
     * if the file is not found, the aliases director is ignored.
     */
    0,					/* no retries */
# else	/* HAVE_RENAME */
    /*
     * without an atomic rename call, there will be short periods
     * of time when the file does not exist, while it is being
     * rebuilt
     */
    2,					/* two retries on open */
# endif	/* HAVE_RENAME */
    10,					/* ten second intervals for retries */
    NULL,				/* internal - open database */
    NULL,				/* internal - error text from open */
};

static struct router rewrite_router = {
    "rewrite",				/* routing through rewriter */
    REWRITE_ROUTER_DRV_NM,		/* use the rewrite driver */
    SUCC,				/* point to next router */
    USE_ALWAYS |			/* we generally want to force rewrite on a match */
# ifdef REWRITE_OPTIONAL
	RW_OPTIONAL |			/* the rewrite file is optional */
# endif
# ifdef REWRITE_TRYAGAIN
	RW_TRYAGAIN |			/* defer address on open failure */
# endif
	RW_REOPEN,			/* always reopen database to search */
    METHOD_TABLE,			/* use method table to find tport */
    NULL,				/* no default transport */
    (char *) &rewrite_router_priv,	/* rewrite private configuration */
};
# undef SUCC
# define SUCC (&rewrite_router)	/* setup for forward link */

#endif /* REWRITE_FILE */


#if defined(FORCE_PATHS_FILE) && defined(PATHALIAS_ROUTER_DRV_NM)
/*
 * FORCE_PATH ROUTER:
 *
 * The name of the force_paths file and the access method type is
 * defined in config.h, if a forcepaths database is configured.
 */
static struct pathalias_private force_paths_router_priv = {
    FORCE_PATHS_FILE,			/* file attribute */
    FORCE_PATHS_PROTO,			/* file access method */
    NULL,				/* default domain names */
    NULL,				/* no required domain names */
# ifdef	HAVE_RENAME
    /*
     * if we have an atomic rename call, retries should not be required
     * since the file should always exist, even when being rebuilt
     *
     * if the file is not found, the aliases director is ignored.
     */
    0,					/* no retries */
# else	/* HAVE_RENAME */
    /*
     * without an atomic rename call, there will be short periods
     * of time when the file does not exist, while it is being
     * rebuilt
     */
    2,					/* two retries on open */
# endif	/* HAVE_RENAME */
    10,					/* ten second intervals for retries */
    NULL,				/* internal - open database */
    NULL,				/* internal - error text from open */
};

static struct router force_paths_router = {
    "force_paths",			/* routing through forcepaths file */
    PATHALIAS_ROUTER_DRV_NM,		/* use the pathalias driver */
    SUCC,				/* point to next router */
    USE_ALWAYS |
# ifdef FORCE_PATHS_OPTIONAL
	PA_OPTIONAL |			/* the paths file is optional */
# endif
# ifdef FORCE_PATHS_TRYAGAIN
	PA_TRYAGAIN |			/* defer address on open failure */
# endif
	PA_REOPEN,			/* always reopen database to search */
    METHOD_TABLE,			/* use method table to find transport */
    FORCE_PATHS_TRANSPORT,		/* default transport */
    (char *) &force_paths_router_priv,	/* force_paths private configuration */
};
# undef SUCC
# define SUCC (&force_paths_router)	/* setup for forward link */

#endif	/* FORCE_PATHS_FILE */


#if defined(FORCE_SMTP_FILE) && defined(PATHALIAS_ROUTER_DRV_NM)
/*
 * FORCE_SMTP ROUTER:
 *
 * The name of the force_smtp file and the access method type is
 * defined in config.h, if a forcesmtp database is configured.
 */
static struct pathalias_private force_smtp_router_priv = {
    FORCE_SMTP_FILE,			/* file attribute */
    FORCE_SMTP_PROTO,			/* file access method */
    NULL,				/* default domain names */
    NULL,				/* no required domain names */
# ifdef	HAVE_RENAME
    /*
     * if we have an atomic rename call, retries should not be required
     * since the file should always exist, even when being rebuilt
     *
     * if the file is not found, the aliases director is ignored.
     */
    0,					/* no retries */
# else	/* HAVE_RENAME */
    /*
     * without an atomic rename call, there will be short periods
     * of time when the file does not exist, while it is being
     * rebuilt
     */
    2,					/* two retries on open */
# endif	/* HAVE_RENAME */
    10,					/* ten second intervals for retries */
    NULL,				/* internal - open database */
    NULL,				/* internal - error text from open */
};

static struct router force_smtp_router = {
    "force_smtp",			/* routing through forcesmtp file */
    PATHALIAS_ROUTER_DRV_NM,		/* use the pathalias driver */
    SUCC,				/* point to next router */
    USE_ALWAYS |
# ifdef FORCE_SMTP_OPTIONAL
	PA_OPTIONAL |			/* the paths file is optional */
# endif
# ifdef FORCE_SMTP_TRYAGAIN
	PA_TRYAGAIN |			/* defer address on open failure */
# endif
	PA_REOPEN,			/* always reopen database to search */
    (struct method *)NULL,		/* no method table */
    FORCE_SMTP_TRANSPORT,		/* default transport */
    (char *) &force_smtp_router_priv,	/* force_paths private configuration */
};
# undef SUCC
# define SUCC (&force_smtp_router)	/* setup for forward link */

#endif	/* FORCE_SMTP_FILE */

#if !defined(NO_USE_SMARTHOST) && defined(SMARTHOST_ROUTER_DRV_NM)
/*
 * SMARTHOST ROUTER:
 *
 * This router allows for declaration of a remote host to which mail should be
 * sent for hosts that we cannot resolve ourselves.  Presumably this remote
 * host has a more complete or more up-to-date collection of routing databases
 * than we do ourselves.
 *
 * Assuming the default configuration with SMART_PATH set to NULL this router
 * will only be enabled if the global smart_path variable is set, but if it
 * smart_path is set then this router will override all the other routers (that
 * come after it, but since this one comes first...).
 */
static struct smarthost_private smarthost_router_priv = {
    SMART_PATH,
    NULL,
    NULL,
};

static struct router smarthost_router = {
    "smart_host",			/* routing to smarthost */
    SMARTHOST_ROUTER_DRV_NM,		/* use the smarthost driver */
    SUCC,				/* point to next router */
    USE_ALWAYS,				/* useless if we don't force a match */
    METHOD_TABLE,			/* use method table, if non-NULL */
    SMART_TRANSPORT,			/* default transport given */
    (char *) &smarthost_router_priv,	/* smarthost private configuration */
};
# undef SUCC
# define SUCC (&smarthost_router)	/* setup for forward link */
#endif	/* !defined(NO_USE_SMARTHOST) */


/* point to the first router */
struct router *routers = SUCC;


/*
 * START OF TRANSPORT DEFINITION SECTION
 *
 * The order is not important for transports.
 */

#undef SUCC
#define SUCC	NULL			/* end of transport list */

/*
 * LOCAL TRANSPORT:
 *
 * Local mail delivery is done either by appending to a file, or by
 * sending to a command.  If a command is defined, as LOCAL_MAIL_COMMAND
 * in config.h, use it.  Otherwise a filename must be defined as
 * LOCAL_MAIL_FILE.  Produce a compile error if nothing is configured.
 */

#if defined(LOCAL_MAIL_COMMAND) && defined(PIPE_TRANSPORT_DRV_NM)

static struct pipe_private local_transport_priv = {
    LOCAL_MAIL_COMMAND,			/* example "/bin/mail -d $($user$) */
    NULL,				/* execute the program as nobody */
    NULL,				/* no specific group */
    0022,				/* umask for child process */
    'b',				/* handle_write_errors */
    "1-127",				/* bounce_child_exitcodes */
    NULL,				/* defer_child_exitcodes */
    "0",				/* ignore_child_exitcodes */
};

static struct transport local_transport = {
    "local",				/* local transport to users */
    PIPE_TRANSPORT_DRV_NM,		/* use the pipe driver */
    SUCC,				/* point to next transport */
    /* put Received:, Return-Path:, will do local delivery, note that
     * mail.local is assumed to add the From_ line itself and to escape From_
     * lines in the message body */
    PUT_RECEIVED | PUT_RETURNPATH | STRICT_TPORT | LOCAL_TPORT | PIPE_STATUS_2SENDER,
# ifdef	LOCAL_MAIL_ADDRS
    /*
     * if there is a specific limit on number of addrs from config.h, use that
     * in assigning transport instances, otherwise the limit defaults to just
     * 1.  The default 2000-char limit is an arbitrary large number that's
     * small enough for all known systems to handle.
     */
    LOCAL_MAIL_ADDRS, 1,		/* limits for assigning transports */
#  if defined(NCARGS) && (NCARGS - 0) > (PATH_MAX * 2)
    NCARGS - (PATH_MAX * 2),
#  else
#   if defined(ARG_MAX) && (ARG_MAX - 0) > (PATH_MAX * 2)
    ARG_MAX - (PATH_MAX * 2),
#   else
    2000,				/* even xenix on 8086 could hack this */
#   endif
#  endif
# else	/* LOCAL_MAIL_ADDRS */
    1, 1, 0,				/* 1 addr, 1 host, size not useful */
# endif	/* LOCAL_MAIL_ADDRS */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    NULL,				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &local_transport_priv,	/* local private configuration */
};

# undef SUCC
# define SUCC (&local_transport)	/* setup for forward link */

#elif defined(APPENDFILE_TRANSPORT_DRV_NM)

static struct appendfile_private local_transport_priv = {
    LOCAL_MAIL_FILE,			/* e.g.: /usr/spool/mail/${user} */
    NULL,				/* directory does not apply */
    NULL,				/* run as the particular user */
    LOCAL_MAIL_GROUP,			/* group used when opening mailboxes */
# if (defined(UNIX_SCO) && !defined(NO_MMDF_MAILBOXES)) || defined(MMDF_MAILBOXES)
    "\001\001\001\001\n",		/* MMDF */
    "\001\001\001\001\n",		/* MMDF */
# else
    NULL,				/* no message prefix */
    "\n",				/* end message with extra newline */
# endif
    LOCAL_MAIL_MODE,			/* file creation mode */
};

static struct transport local_transport = {
    "local",				/* local transport to users */
    APPENDFILE_TRANSPORT_DRV_NM,	/* use the appendfile driver */
    SUCC,				/* point to next transport */
    /* put Received:, Return-Path: and From_ line, will do local delivery */
    PUT_RECEIVED | PUT_RETURNPATH | STRICT_TPORT | LOCAL_TPORT | PUT_FROM |
	APPEND_AS_USER |		/* use uid/gid from addr structure */
	APPEND_CHECK_USER |		/* make sure $user is safe (no /) */
#if (!defined(UNIX_SCO) || defined(NO_MMDF_MAILBOXES)) && !defined(MMDF_MAILBOXES)
	UNIX_FROM_HACK |
# endif
	APPEND_COMSAT,
    1, 1, 0,				/* 1 addr, 1 host, size not useful */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    NULL,				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &local_transport_priv,	/* local private configuration */
};

# undef SUCC
# define SUCC (&local_transport)	/* setup for forward link */

#endif	/* LOCAL_MAIL_COMMAND */


#if defined(USE_CYRUS_IMAPD) && defined(PIPE_TRANSPORT_DRV_NM)
/*
 * CYRUS_DELIVER TRANSPORT:
 *
 */
static struct pipe_private cyrus_deliver_transport_priv = {
    CYRUS_DELIVER_COMMAND,		/* command is passed as next_addr */
    NULL,				/* run as ? */
    "${cyrus_group}",			/* "deliver" can only be run by the right group */
    0022,				/* umask for child process */
    'd',				/* handle_write_errors */
    "1-63:65-74:76:77:79-127",		/* bounce_child_exitcodes */
    "64:75:78",				/* EX_USAGE, EX_TEMPFAIL, and EX_CONFIG
					 * are the true "temporary" errors for
					 * Cyrus 2.1.15 deliver. */
    "0",				/* ignore_child_exitcodes */
};

static struct transport cyrus_deliver_transport = {
    "cyrus_deliver",			/* pipe transport to Cyrus IMAP's "deliver" */
    PIPE_TRANSPORT_DRV_NM,		/* use the pipe driver */
    SUCC,				/* point to next transport */
    /* put Recieved:, will do local delivery */
    PUT_RECEIVED | STRICT_TPORT | LOCAL_TPORT |
	PIPE_LOG_OUTPUT | PIPE_STATUS_2SENDER,
    1, 1, 0,				/* 1 addr, 1 host, size not useful */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    NULL,				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &cyrus_deliver_transport_priv, /* cyrus_deliver private configuration */
};
# undef SUCC
# define SUCC (&cyrus_deliver_transport) /* setup for forward link */

/*
 * CYRUS_DELIVER_NOQUOTA TRANSPORT:
 *
 */
static struct pipe_private cyrus_deliver_nq_transport_priv = {
    CYRUS_DELIVER_NQ_COMMAND,		/* command is passed as next_addr */
    NULL,				/* run as ? */
    "${cyrus_group}",	    		/* "deliver" can only be run by the right group */
    0022,				/* umask for child process */
    'd',				/* handle_write_errors */
    "1-63:65-74:76:77:79-127",		/* bounce_child_exitcodes */
    "64:75:78",				/* EX_USAGE, EX_TEMPFAIL, and EX_CONFIG
					 * are the true "temporary" errors for
					 * Cyrus 2.1.15 deliver. */
    "0",				/* ignore_child_exitcodes */
};

static struct transport cyrus_deliver_nq_transport = {
    "cyrus_deliver_noquota",		/* pipe transport to the cyrus-deliver-noquota filter */
    PIPE_TRANSPORT_DRV_NM,		/* use the pipe driver */
    SUCC,				/* point to next transport */
    /* put Recieved:, will do local delivery */
    PUT_RECEIVED | STRICT_TPORT | LOCAL_TPORT |
	PIPE_LOG_OUTPUT | PIPE_STATUS_2SENDER,
    1, 1, 0,				/* 1 addr, 1 host, size not useful */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    NULL,				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &cyrus_deliver_nq_transport_priv, /* cyrus_deliver private configuration */
};
# undef SUCC
# define SUCC (&cyrus_deliver_nq_transport) /* setup for forward link */

#endif /* USE_CYRUS_IMAPD */

#if defined(PIPE_TRANSPORT_DRV_NM)
/*
 * PIPE TRANSPORT:
 *
 * Run a shell command by piping the message to the shell.  Shell
 * commands can only be produced if the aliasfile and forwardfile
 * drivers are used.
 *
 * Note that if the command starts with '$' it will be passed to
 * expand_string() before it is passed to build_cmd_line().
 */
static struct pipe_private pipe_transport_priv = {
    PIPE_COMMAND,			/* command is passed as next_addr */
    NULL,				/* use uid of the recipient */
    NULL,				/* use gid of the recipient */
    0022,				/* umask for child process */
    'b',				/* handle_write_errors */
    "1-127",				/* bounce_child_exitcodes */
    NULL,				/* defer_child_exitcodes */
    "0",				/* ignore_child_exitcodes */
};

static struct transport pipe_transport = {
    PIPE_TRANSPORT_NM,			/* pipe transport to shell commands */
    PIPE_TRANSPORT_DRV_NM,		/* use the pipe driver */
    SUCC,				/* point to next transport */
    /* put Recieved:, Return-Path: and From_ line, will do local delivery */
    PUT_RECEIVED | PUT_RETURNPATH | STRICT_TPORT | LOCAL_TPORT | PUT_FROM |
	UNIX_FROM_HACK |		/* XXX ??? better safe than sorry? */
	PIPE_AS_USER | PIPE_PARENT_ENV | PIPE_LOG_OUTPUT | PIPE_STATUS_2SENDER,
    1, 1, 0,				/* 1 addr, 1 host, size not useful */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    NULL,				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &pipe_transport_priv,	/* pipe private configuration */
};
# undef SUCC
# define SUCC (&pipe_transport)		/* setup for forward link */

#endif /* PIPE_TRANSPORT_DRV_NM */

#if defined(APPENDFILE_TRANSPORT_DRV_NM)
/*
 * FILE TRANSPORT:
 *
 * Append to a specific filename.  File addresses can only be produced
 * if the aliasfile and forwardfile drivers are used.
 */
static struct appendfile_private file_transport_priv = {
    "$user",				/* the file is passed as next_addr */
    NULL,				/* no dir attribute */
    NULL,				/* use uid of the recipient */
    NULL,				/* use gid of the recipient */
# if (defined(UNIX_SCO) && !defined(NO_MMDF_MAILBOXES)) || defined(MMDF_MAILBOXES)
    "\001\001\001\001\n",		/* MMDF */
    "\001\001\001\001\n",		/* MMDF */
# else
    NULL,				/* prefix string */
    "\n",				/* suffix string */
# endif
    0644,				/* mode for creation */
};

static struct transport file_transport = {
    FILE_TRANSPORT_NM,			/* append to specific files */
    APPENDFILE_TRANSPORT_DRV_NM,	/* use the apppendfile driver */
    SUCC,				/* point to next transport */
    /* put Recieved:, Return-Path: and From_ line, will do local delivery */
    PUT_RECEIVED | PUT_RETURNPATH | STRICT_TPORT | LOCAL_TPORT | PUT_FROM |
# if (!defined(UNIX_SCO) || defined(NO_MMDF_MAILBOXES)) && !defined(MMDF_MAILBOXES)
	UNIX_FROM_HACK |
# endif
	/* also append to file with uid/gid from addr structure */
	APPEND_AS_USER |
	/* expand the user name so ~ expansions can occur */
	APPEND_EXPAND_USER,
    1, 1, 0,				/* 1 addr, 1 host, size not useful */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    NULL,				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &file_transport_priv,	/* pipe private configuration */
};
# undef SUCC
# define SUCC (&file_transport)		/* setup for forward link */
#endif /* APPENDFILE_TRANSPORT_DRV_NM */

#if !defined(NO_UUCP_TRANSPORTS) && defined(PIPE_TRANSPORT_DRV_NM)
/*
 * UUX TRANSPORT:
 *
 * This calls uux with the -r flag so that actual delivery is not
 * attempted immediately.  Presumably a cronjob will start up uucico at
 * some later time to actually attempt to send the mail to the remote
 * machine.
 *
 * The message is transferred in UUCP format with envelope addresses in UUCP
 * format.
 */
static struct pipe_private uux_transport_priv = {
    QUEUED_UUX_COMMAND,			/* queued uux to remote rmail */
    /* to run uux as other than the nobody user, put the login name here */
    NULL,				/* execute the program as nobody */
    NULL,				/* no specific group */
    0022,				/* umask for child process */
    'b',				/* handle_write_errors */
    "1-127",				/* bounce_child_exitcodes */
    NULL,				/* defer_child_exitcodes */
    "0",				/* ignore_child_exitcodes */
};

static struct transport uux_transport = {
    "uux",				/* queued transport over uux */
    PIPE_TRANSPORT_DRV_NM,		/* uses pipe transport driver */
    SUCC,				/* point to next transport */
    /* only use !-routes in message envelope, supply a Received: field
     * and begin the message with a From_ line. */
    UUCP_XFORM | PUT_RECEIVED | PUT_FROM | PIPE_AS_SENDER | PIPE_LOG_OUTPUT,
    5, 1, 200,				/* 5 addresses, 1 host, 200 chars */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    NULL,				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &uux_transport_priv,	/* uux private configuration */
};
# undef SUCC
# define SUCC (&uux_transport)		/* setup for forward link */

/*
 * DEMAND TRANSPORT:
 *
 * This calls uux _without_ the -r flag so that delivery _is_ attempted
 * immediately.  Presumably a cronjob will start up uucico at some later time
 * to actually attempt to send the mail to the remote machine.
 *
 * The message is transferred in UUCP format with envelope addresses in UUCP
 * format.
 */
static struct pipe_private demand_transport_priv = {
    DEMAND_UUX_COMMAND,			/* demand uux to remote rmail */
    /* to run uux as other than the nobody user, put the login name here */
    NULL,				/* execute the program as nobody */
    NULL,				/* no specific group */
    0022,				/* umask for child process */
    'b',				/* handle_write_errors */
    "1-127",				/* bounce_child_exitcodes */
    NULL,				/* defer_child_exitcodes */
    "0",				/* ignore_child_exitcodes */
};

static struct transport demand_transport = {
    "demand",				/* immediate transport over uux */
    PIPE_TRANSPORT_DRV_NM,		/* uses pipe transport driver */
    SUCC,				/* point to next transport */
    /* only use !-routes in message envelope, supply a Received: field
     * and begin the message with a From_ line. */
    UUCP_XFORM | PUT_RECEIVED | PUT_FROM | PIPE_AS_SENDER | PIPE_LOG_OUTPUT,
    5, 1, 200,				/* 5 addresses, 1 host, 200 chars */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    NULL,				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &demand_transport_priv,	/* demand private configuration */
};
#undef SUCC
#define SUCC (&demand_transport)	/* setup for forward link */


/*
 * QUEUED UUSMTP TRANSPORT:
 *
 * This calls uux _with_ the -r flag so that actual delivery is _not_ attempted
 * immediately.  Presumably a cronjob will start up uucico at some later time
 * to actually attempt to send the mail to the remote machine.
 *
 * The message is transferred in BSMTP format with envelope addresses in UUCP
 * format.
 */
static struct pipe_private uusmtp_transport_priv = {
    QUEUED_UUSMTP_COMMAND,		/* queued uux to remote rsmtp */
    /* to run uux as other than the nobody user, put the login name here */
    NULL,				/* execute the program as nobody */
    NULL,				/* no specific group */
    0022,				/* umask for child process */
    'b',				/* handle_write_errors */
    "1-127",				/* bounce_child_exitcodes */
    NULL,				/* defer_child_exitcodes */
    "0",				/* ignore_child_exitcodes */
};

static struct transport uusmtp_transport = {
    "uusmtp",				/* demand transport over uux */
    PIPE_TRANSPORT_DRV_NM,		/* uses pipe transport driver */
    SUCC,				/* point to next transport */
    /* supply a Received: field
     * and put an SMTP envelope around the message. */
    UUCP_XFORM | PUT_RECEIVED | BSMTP_TPORT | PIPE_AS_SENDER | PIPE_LOG_OUTPUT,
    0, 1, 0,				/* 1 host */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    NULL,				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &uusmtp_transport_priv,	/* demand private configuration */
};
#undef SUCC
#define SUCC (&uusmtp_transport)	/* setup for forward link */


/*
 * DEMAND UUSMTP TRANSPORT:
 *
 * This calls uux _without_ the -r flag so that actual delivery _is_ attempted
 * immediately.  Presumably a cronjob will start up uucico at some later time
 * to actually attempt to send the mail to the remote machine.
 *
 * The message is transferred in BSMTP format with envelope addresses in UUCP
 * format.
 */
static struct pipe_private demand_uusmtp_transport_priv = {
    DEMAND_UUSMTP_COMMAND,		/* demand uux to remote rsmtp */
    /* to run uux as other than the nobody user, put the login name here */
    NULL,				/* execute the program as nobody */
    NULL,				/* no specific group */
    0022,				/* umask for child process */
    'b',				/* handle_write_errors */
    "1-127",				/* bounce_child_exitcodes */
    NULL,				/* defer_child_exitcodes */
    "0",				/* ignore_child_exitcodes */
};

static struct transport demand_uusmtp_transport = {
    "demand_uusmtp",			/* demand transport over uux */
    PIPE_TRANSPORT_DRV_NM,		/* uses pipe transport driver */
    SUCC,				/* point to next transport */
    /* supply a Received: field
     * and put an SMTP envelope around the message. */
    UUCP_XFORM | PUT_RECEIVED | BSMTP_TPORT | PIPE_AS_SENDER | PIPE_LOG_OUTPUT,
    0, 1, 0,				/* 1 host */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    NULL,				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &demand_uusmtp_transport_priv, /* demand private configuration */
};
#undef SUCC
#define SUCC (&demand_uusmtp_transport)	/* setup for forward link */


/*
 * INET QUEUED UUSMTP TRANSPORT:
 *
 * This calls uux with the -r flag so that actual delivery is not
 * attempted immediately.  Presumably a cronjob will start up uucico at
 * some later time to actually attempt to send the mail to the remote
 * machine.
 *
 * The message is transferred in BSMTP format with envelope addresses in
 * Interntet form.
 */
static struct pipe_private inet_uusmtp_transport_priv = {
    QUEUED_UUSMTP_COMMAND,		/* queued uux to remote rsmtp */
    /* to run uux as other than the nobody user, put the login name here */
    NULL,				/* execute the program as nobody */
    NULL,				/* no specific group */
    0022,				/* umask for child process */
    'b',				/* handle_write_errors */
    "1-127",				/* bounce_child_exitcodes */
    NULL,				/* defer_child_exitcodes */
    "0",				/* ignore_child_exitcodes */
};

static struct transport inet_uusmtp_transport = {
    "inet_uusmtp",			/* batched smtp transport over uux */
    PIPE_TRANSPORT_DRV_NM,		/* uses pipe transport driver */
    SUCC,				/* point to next transport */
    /* supply a Received: field
     * and put an SMTP envelope around the message. */
    INET_XFORM | PUT_RECEIVED | STRICT_TPORT | BSMTP_TPORT | PIPE_AS_SENDER | PIPE_LOG_OUTPUT,
    0, 1, 0,				/* 1 host */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    NULL,				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &inet_uusmtp_transport_priv, /* demand private configuration */
};
#undef SUCC
#define SUCC (&inet_uusmtp_transport)	/* setup for forward link */


/*
 * INET DEMAND UUSMTP TRANSPORT:
 *
 * This calls uux without the -r flag so that actual delivery is
 * attempted immediately.
 *
 * The message is transferred in BSMTP format with envelope addresses in
 * Internet form.
 */
static struct pipe_private idemand_uusmtp_transport_priv = {
    DEMAND_UUSMTP_COMMAND,		/* demand uux to remote rsmtp */
    /* to run uux as other than the nobody user, put the login name here */
    NULL,				/* execute the program as nobody */
    NULL,				/* no specific group */
    0022,				/* umask for child process */
    'b',				/* handle_write_errors */
    "1-127",				/* bounce_child_exitcodes */
    NULL,				/* defer_child_exitcodes */
    "0",				/* ignore_child_exitcodes */
};

static struct transport idemand_uusmtp_transport = {
    "inet_demand_uusmtp",		/* demand transport over uux */
    PIPE_TRANSPORT_DRV_NM,		/* uses pipe transport driver */
    SUCC,				/* point to next transport */
    /* supply a Received: field
     * and put an SMTP envelope around the message. */
    INET_XFORM | PUT_RECEIVED | STRICT_TPORT | BSMTP_TPORT | PIPE_AS_SENDER | PIPE_LOG_OUTPUT,
    0, 1, 0,				/* 1 host */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    NULL,				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &idemand_uusmtp_transport_priv,
    					/* demand private configuration */
};
#undef SUCC
#define SUCC (&idemand_uusmtp_transport) /* setup for forward link */

#endif /* !NO_UUCP_TRANSPORTS */

#if defined(USE_SMTP_TRANSPORT) && defined(TCPSMTP_TRANSPORT_DRV_NM)

# ifndef SMTP_SHORT_TIMEOUT
#  define SMTP_SHORT_TIMEOUT	(5*60)	/* short timeout, 5 minutes */
# endif

# ifndef SMTP_LONG_TIMEOUT
#  define SMTP_LONG_TIMEOUT	(5*60*60) /* long timeout, 5 hours */
# endif

# ifndef SMTP_SERVICE_ENTRY
# define SMTP_SERVICE_ENTRY	"smtp"	/* use the "smtp" service */
# endif

/*
 * SMTP TRANSPORTS:
 *
 * This initiates an SMTP conversation with a remote host over TCP/IP.
 *
 * The "uucp_zone_smtp" transport transfers in uucp format.
 * The "inet_zone_smtp" transport transfers in internet format.
 */

static struct tcpsmtp_private smtp_transport_priv = {
    SMTP_SHORT_TIMEOUT,
    SMTP_LONG_TIMEOUT,
    SMTP_SERVICE_ENTRY,
# if defined(HAVE_BIND)
    BIND_TEMPLATE_ATTRIBUTES,
# endif
};

# if !defined(NO_UUCP_TRANSPORTS)
static struct transport uucp_zone_smtp_transport = {
    "uucp_zone_smtp",			/* smtp to remote uucp-zone host */
    TCPSMTP_TRANSPORT_DRV_NM,		/* uses smtp transport driver */
    SUCC,				/* point to next transport */
    UUCP_XFORM |
	PUT_RECEIVED,			/* write a Received: field */
    0, 1, 0,				/* 1 host, no other limit */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    "smtp",				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &smtp_transport_priv,	/* generic smtp private configuration */
};
#  undef SUCC
#  define SUCC (&uucp_zone_smtp_transport) /* setup for forward link */
# endif

static struct transport inet_zone_smtp_transport = {
    "inet_zone_smtp",			/* smtp to remote internet host */
    TCPSMTP_TRANSPORT_DRV_NM,		/* uses smtp transport driver */
    SUCC,				/* point to next transport */
    INET_XFORM | STRICT_TPORT |
	PUT_RECEIVED,			/* write a Received: field */
    0, 1, 0,				/* 1 host, no other limit */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    "smtp",				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &smtp_transport_priv,	/* generic smtp private configuration */
};
# undef SUCC
# define SUCC (&inet_zone_smtp_transport) /* setup for forward link */

# if defined(HAVE_BIND) && defined(USE_BIND)
static struct transport inet_zone_bind_smtp_transport = {
    "inet_zone_bind_smtp",		/* smtp to remote host */
    TCPSMTP_TRANSPORT_DRV_NM,		/* uses smtp transport driver */
    SUCC,				/* point to next transport */
    BIND_DEFER_NO_CONN |		/* this makes more sense for modern DNS hosts */
	BIND_DOMAIN_REQUIRED |
	TCPSMTP_USE_BIND |
	INET_XFORM | STRICT_TPORT |
	PUT_RECEIVED,			/* write a Received: field */
    0, 1, 0,				/* 1 host, no other limit */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    "smtp",				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &smtp_transport_priv,	/* no private configuration */
};
#  undef SUCC
#  define SUCC (&inet_zone_bind_smtp_transport) /* setup for forward link */

#  if !defined(NO_UUCP_TRANSPORTS)
static struct transport uucp_zone_bind_smtp_transport = {
    "uucp_zone_bind_smtp",		/* smtp to remote uucp-zone host */
    TCPSMTP_TRANSPORT_DRV_NM,		/* uses smtp transport driver */
    SUCC,				/* point to next transport */
    BIND_DEFER_NO_CONN |		/* this makes more sense for modern DNS hosts */
	BIND_DOMAIN_REQUIRED |
	TCPSMTP_USE_BIND |
	UUCP_XFORM |			/* this probably isn't of much use.... */
	PUT_RECEIVED,			/* write a Received: field */
    0, 1, 0,				/* 1 host, no other limit */
    NULL, NULL, NULL,			/* hdrremove, hdrinsert, hdrappend */
    "smtp",				/* retry directory */
    NULL,				/* shadow transport */
    NULL,				/* error transport */
    (char *) &smtp_transport_priv,	/* generic smtp private configuration */
};
#   undef SUCC
#   define SUCC (&uucp_zone_bind_smtp_transport) /* setup for forward link */
#  endif /* !NO_UUCP_TRANSPORTS */

# endif /* HAVE_BIND && USE_BIND */

#endif	/* USE_SMTP_TRANSPORT */


/* point to the first transport */
struct transport *transports = SUCC;
struct transport *builtin_transports = SUCC;

/* 
 * Local Variables:
 * c-file-style: "smail"
 * End:
 */
