/*
 * sendmail-thor.ease -- sendmail config file for thor, written
 * 			in ease
 *
 * 	$Source: /mit/tytso/projects/ease/conf/RCS/thor.ease,v $
 * 	$Header: thor.ease,v 1.1 88/09/05 03:50:45 tytso Locked $
 * 	$Author: tytso $
 */

#define MAILHUB 	"ATHENA.MIT.EDU"
#define LOCALUSERS	"/usr/lib/localusers"
#define CHAOSHOSTS	"/usr/lib/chaoshosts"

#define CSNET_RELAY	RELAY.CS.NET
#define BITNET_RELAY	MITVMA.MIT.EDU
#define MAILNET_RELAY	UMIX.CC.UMICH.EDU
#define ENET_RELAY	"decvax!decwrl!rhea"

bind
	BASE_RW			= ruleset 0;
	SENDER_PREWRITE         = ruleset 1;
	RECIPIENT_PREWRITE      = ruleset 2;
	NAME_CANON              = ruleset 3;
	FINAL_POSTWRITE         = ruleset 4;
	LOCAL_RW		= ruleset 6;
	RULESET_8		= ruleset 8;
	LOCALUSER_RW		= ruleset 9;
	MAGIC_RW                = ruleset 10;
	UUCP_SENDER_RW          = ruleset 14;
	UNIMPLEMENTED		= ruleset 20;
	UUCP_RECIPIENT_RW       = ruleset 24;
	TCP_SENDER_RW           = ruleset 27;
	TCP_RECIPIENT_RW        = ruleset 28;

/* Modified for Domain style names. 05/26/85 by Jeffrey I. Schiller */
/* Actually, most of this file is stolen directly from eddie's, in order */
/* to handle uucp addresses. -- AMBAR 5/19/87 */
/* Hacked in Cw line to allow mail to be sent to beacon.mit.edu -- SRZ 9/13/87 */

/* ############################################################ */

/* SENDMAIL CONFIGURATION FILE */

/* @(#)athena.mc	2.0		4/19/84 */

/* ############################################################ */

/*
 * local info
 */
class
#ifdef notdef
	D = { "MIT" . "EDU" };	/* domain names */
#endif
	m_sitename = { THOR };	/* Names that this machine 
				 is also known as */

/* Temporary bogus "domains" which should not go outside this machine */
	bogus_domains = { UUX, TCP, UUCPS };
#ifdef CHAOSHOSTS
	chaoshosts = readclass(CHAOSHOSTS);
#endif
#ifdef LOCALUSERS
	localusers = readclass(LOCALUSERS);
#endif

macro
	D = "MIT.EDU";		/* #domain names */
	E = ENET_RELAY;		/* ENET relay */
#ifdef MAILHUB
	mailhub = MAILHUB;	/* Mailhub to forward mail to */
#endif
	m_oname = "${m_sitename}";	/* #official name */
	U = "thor";			/* UUCP name */
	version = "4.7";

/*
 * General configuration information
 * This information is basically just "boiler-plate"; it must be 
 * there, but is essentially constant.
 * 
 *  Information in this file should be independent of location --
 * i.e., although there are some policy decisions made, they are 
 * not specific to Berkeley per se.
 * 
 * @(#)base.m4	4.3		8/30/83
 *
 */

/*
 * Special macros
 */

	m_daemon = "MAILER-DAEMON";		/* my name */
	m_ufrom = "From ${m_sreladdr}  ${m_udate}"; /* UNIX header format */
	m_addrops = ".:%@!^=/[]";	/* delimiter (operator) characters */

	/* format of a total name */
	m_defaddr = concat(ifset(m_sname, "${m_sname} "), "<${m_sreladdr}>");
#ifdef notdef
	m_defaddr = concat("${m_sreladdr}", ifset(m_sname, " (${m_sname})"));
#endif

	/* SMTP login message */
	m_smtp = "${m_oname} Sendmail ${m_version}/${version} ready to play at ${m_adate}";

#ifdef notdef
/* forwarding host -- redefine this if you can't talk to the relay directly */
	F = "${R}";
#endif

/* 
 * Options
 */

options
	o_alias = "/usr/lib/aliases";	/* location of alias file */
	o_delivery = d_background;	/* default delivery mode */

#ifdef notdef
	o_qwait = "";			/* (don't) connect to "expensive"
					 * mailers immediately */
#endif

	o_tmode = "0644";		/* temporary file mode */
	o_gid = "1";			/* default GID */
	o_fsmtp = "/usr/lib/sendmail.hf";	/* location of help file */
	o_slog = "9";			/* log level */
	o_hformat = "";			/* default messages to old style */
	o_qdir = "/usr/spool/mqueue";	/* queue directory */
	o_tread = "2h";			/* read timeout -- violates 
					 * protocols */

	o_flog = "/usr/lib/sendmail.st";/* status file */
	o_safe = "";			/* queue up everything before 
					 * starting transmission */

	o_qtimeout = "3d";		/* default timeout interval */
	o_timezone = "EST,EDT";		/* time zone names (V6 only) */
	o_dmuid = "1";			/* default UID */
	o_wizpass = "*";	/* wizard's password */

/* 
 * Message precedences
 */
precedence
	first-class = 0;
	special-delivery = 100;
	junk = -100;

/*
 * Trusted users
 */
trusted
	{ root, daemon, uucp, network };

/*
 * Format of headers
 */
header
	for (f_return) {
		define ("Return-Path:", " <${m_sreladdr}>");
	};

	define ("Received:",
		ifset (m_shostname, " from ${m_shostname}")
		" by ${m_oname}"
#ifdef notdef
		ifset (Q, " via ${Q}")
#endif
		ifset (m_protocol, " with ${m_protocol}")
#ifdef notdef
		ifset (P, " with ${P}" )
#endif
		" with sendmail-${m_version}/${version} \
id <${m_qid}@${m_oname}>; ${m_adate}");

	for (f_date) {
		define ("Resent-Date:", " ${m_odate}");
		define ("Date:", " ${m_odate}");
	};

	for (f_from) {
		define ("Resent-From:", " ${m_defaddr}");
		define ("From:", " ${m_defaddr}");
	};

	for (f_full) {
		define ("Full-Name:", " ${m_sname}");
	};

	define ("Subject:", "");

#ifdef notdef
	define ("Posted-Date:", " ${m_odate}");

	for (f_locm) {
		define ("Received-Date:", " ${m_adate}");
	};
#endif

	for (f_mesg) {
		define ("Resent-Message-Id:",
			" <${m_ctime}.${m_qid}@${m_oname}>");
		define ("Message-Id:",
			" <${m_ctime}.${m_qid}@${m_oname}>");
	};


/* 
 * Rewriting rules
 */

field
	zero_or_more : match (0*);
	one_or_more : match (1*);
	exactly_one : match (1);

	bogus_domain : match (1) in bogus_domains;

	anypath                 : match (0*);
	path, usr, hostpath,
	domain                  : match (1*);
	this_host               : match (1) in m_sitename;
	hostname, username	: match (1);
#ifdef CHAOSHOSTS
	chaoshost		: match (1) in chaoshosts;
#endif
#ifdef LOCALUSERS
	localuser		: match (1) in localusers;
	non_localuser		: match (0) in localusers;
#endif


/*
 * Sender field pre-rewriting
 */
ruleset
	SENDER_PREWRITE {
#ifdef notdef
	if ( username ) 
		retry ($1@$m_oname);
#endif
#ifdef notdef
	if ( anypath < anypath > anypath )	/* defocus */
		retry ($1$2$3);
#endif
	}

/*
 * Recipient field pre-rewriting
 */
ruleset
	RECIPIENT_PREWRITE {
#ifdef notdef
	if ( anypath < anypath > anypath )	/* defocus */
		retry ($1$2$3);
#endif
	}

/*
 * Final output post-rewriting
 */

ruleset
	FINAL_POSTWRITE {

	if (@)	
		return ();			/* handle <> error addr */
	if ( anypath < path > anypath )	
		retry ($1$2$3);			/* defocus */

/* Remove internal uucp syntax marker */
	if ( usr @ hostpath ."UUCPS" anypath )	
		retry ($2!$1$3);		/* u@h.UUCPS => h!u */

/* Remove bogus routing "domains" */
	if ( usr @ hostpath . bogus_domain anypath )
		retry ($1@$2$4);

/* delete duplicate local names -- mostly for arpaproto.mc */
	if ( anypath @ this_host .$D: hostpath @ this_host .$D)
		retry ($1$3@$m_oname);		/* @ucb:u@ucb => u@ucb */
	if ( usr % this_host @ this_host )	
		retry ($1@$m_oname);		/* u%UCB@UCB => u@UCB */
	if ( usr % this_host @ this_host .$D)	
		retry ($1@$m_oname);		/* u%UCB@UCB => u@UCB */
	if ( usr % this_host .$D@ this_host .$D)	
		retry ($1@$m_oname);		/* u%UCB@UCB => u@UCB */
	if ( this_host ! usr @ this_host .$D)	
		retry ($2@$m_oname);		/* ucb!u@ucb => u@ucb */

#ifdef notdef
	if ( usr % this_host @ this_host ."MIT"."EDU")
		retry ($1@$3."MIT"."EDU");
#endif

	if (@ hostpath : hostpath : hostpath )	
		return (@$1,$2:$3);		/* <route-addr> canonical */
	}

/* ########################### */
/* #  Name Canonicalization  # */
/* ########################### */

ruleset
	NAME_CANON {

	/* handle "from:<>" special case */
	if (<>)	/* turn into magic token */
		return (@);

	/* basic textual canonicalization */
	if ( anypath < path > anypath )	/* basic RFC821/822 parsing */
		retry ($2);
	if ( usr " at " path )	/* "at" -> "@" for RFC 822 */
		retry ($1@$2);
	if ( anypath < anypath > anypath )	/* in case recursive */
		retry ($1$2$3);

	/* 
	 * make sure <@a,@b,@c:user@d> syntax is easy to parse --
	 * (undone later)
	 */
	if (@ path , usr )	/* change all "," to ":" */
		retry (@$1:$2);

	/* localize and dispose of domain-based addresses */
	if (@ path : usr )	/* handle <route-addr> */
		return (LOCAL_RW (<@$1>:$2));

	/* more miscellaneous cleanup */
	if ( path )	/* host dependent cleanup */
		next (RULESET_8 ($1));
	if ( path : anypath ;@ domain )	/* list syntax */
		return ($1:$2;@$3);
	if ( usr @ domain )	/* focus on domain */
		next ($1<@$2>);
#ifdef notdef
/* #Line below edited 5/4/85 to be line below it. This prevents mailer loop */
	if ( path < path @ domain >)	/* move gaze right */
		retry ($1$2<@$3>);
#endif
	if ( path < path @ domain >)	/* move gaze right */
		next ($1$2<@$3>);
	if ( usr <@ hostpath >)	/* already canonical */
		return (LOCAL_RW ($1<@$2>));

	/* convert old-style addresses to a domain-based address */
	if ( usr % hostname )			/* user%hosta%hostb */
		return (LOCAL_RW ($1<@$2>));
	if ( usr % hostname )		/* user%host */
		return (LOCAL_RW ($1<@$2>));
	if ( hostname : usr )			/* host:user */
		return (LOCAL_RW ($2<@$1>));
#ifdef notdef
	if ( hostname . usr )			/* host.user */
		return (LOCAL_RW ($2<@$1>));
#endif
	if ( hostname ^ usr )		/* convert ^ to ! */
		retry ($1!$2);
	if ( one_or_more ! exactly_one . one_or_more ! one_or_more )
		next ($2.$3!$4);		/* prefer domain to route */
#ifdef notdef
	if ( domain .! hostpath )	/* domain.!host */
		return (LOCAL_RW ($2<@$1>));
#endif
	if ( hostname ! usr )			/* adjacent uucp names */
		return (LOCAL_RW ($2<@$1."UUCPS">));
	if ( domain ! hostpath )	/* domain!host */
		return (LOCAL_RW ($2<@$1>));
	if ( hostname = usr )			/* resolve bitnet names */
		return (LOCAL_RW ($2<@$1."BITNET">));
	}

/*
 * 	RULESET ZERO PREAMBLE
 *
 *	The beginning of ruleset zero is constant through all 
 * configurations.
 *
 * 		@(#)zerobase.m4	4.1		7/25/83
 */

ruleset
	BASE_RW {

	/* first make canonical */
	if ( anypath < anypath > anypath )
		retry ($1$2$3);			/* defocus */
	if ( path )
		next (NAME_CANON ($1));		/* make canonical */

	/* handle special cases..... */
	if (@)	
		resolve (mailer (local),
			 user("MAILER-DAEMON"));	/* handle <> form */
	if ( anypath <@[ path ]> anypath )	
		resolve (mailer (tcp),
				host ([$2]),
				user ($1@[$2]$3)); /* numeric internet spec */

	/* now delete the local info */
	if ( anypath < anypath  this_host ."LOCAL"> anypath )
		retry ($1<$2>$4);		/* thishost.LOCAL */
	if ( anypath < anypath  this_host ."ARPA"> anypath )
		retry ($1<$2>$4);		/* thishost.parentdomain */
	if ( anypath < anypath  this_host ."UUCPS"> anypath )
		retry ($1<$2>$4);		/* thishost.parentdomain */
	if ( anypath < anypath  this_host ."Athena"> anypath )
		retry ($1<$2>$4);
	if ( anypath < anypath  this_host ."MIT"."EDU"> anypath )
		retry ($1<$2>$4);		/* thishost */
	if ( anypath < anypath  this_host .$D> anypath )
		retry ($1<$2>$4);		/* thishost.parentdomain */
	if ( anypath < anypath  this_host > anypath )
		retry ($1<$2>$4);		/* thishost */
	if ( anypath < anypath .> anypath )
		retry ($1<$2>$3);		/* drop trailing dot */
	if (<@>: anypath )
		return (BASE_RW ($1));		/* retry after route strip */
	if ( anypath <@>)
		return (BASE_RW ($1));		/* strip null trash & retry */

/*
 * End of ruleset zero preamble
 */

/*
 * Machine dependent part of rulset zero
 */

	/* First Process local mail (for now, there are no "local" hosts). */

	if ( anypath <@ anypath ."LOCAL"> anypath )
		resolve (mailer (tcp),
				host ($2),
				user ("$1<@$2.LOCAL>$3"));
#ifdef notdef
	/* strip off parent domain from host names of our parent domain */
	if ( anypath <@ any_in_S .$D> anypath )	/*  */
		retry ($1<@$2>$3);
	/*
	 * Hack to send directly any mail routed through ANY athena host
	 * in same domain
	 */
	if ( one_or_more % one_or_more <@ any_in_S .$D> anypath )
		return (BASE_RW ($1<@$2>$4));
	if ( one_or_more @ one_or_more <@ any_in_S .$D> anypath )
		return (BASE_RW ($1<@$2>$4));
#endif

/* Handle user-specified delivery: */
	if ( anypath <@ hostpath ."BITNET"> anypath )
		resolve (mailer (tcp),
				host (BITNET_RELAY),
				user ("$1<@$2.BITNET>$3"));
	if ( anypath <@ hostpath ."MAILNET"> anypath )
		resolve (mailer (tcp),
				host (MAILNET_RELAY),
				user ("$1<@$2.MAILNET>$3"));
	if ( anypath <@ hostpath ."CSNET"> anypath )
		resolve (mailer (tcp),
				host (CSNET_RELAY),
				user ("$1<@$2.CSNET>$3"));
	if ( anypath <@ hostpath ."TCP"> anypath )
		resolve (mailer (tcp),
				host ($2),
				user ("$1<@$2>$3"));
	if ( anypath <@ hostpath ."UUX"> anypath )
		resolve (mailer (uucp),
				host ($2),
				user ("$1$3"));
#ifdef CHAOSHOSTS
	/* chaosnet */
	if ( hostpath <@ chaoshost >)
		resolve (mailer (tcp),
				host (MC.MIT.EDU),
				user ("$1%$2<@MIT-MC.ARPA>"));
#endif CHAOSHOSTS
	/* resolve names that go into the DEC ENET */
	if ( anypath <@ hostpath ."ENET">)
		retry ($E!$2!$1);

#ifdef notdef
	/* Send mail on the parent domain NOW. */
	if ( anypath <@ hostpath .$D> anypath )
		resolve (mailer (tcp),
				host ($2.$D),
				user ("$1<@$2.$D>$3"));
#endif

	/* special case ...!nondomain must be uucp */
	if ( anypath <@ hostname ."UUCPS"> anypath )
		resolve (mailer (uucp),
				host ($2),
				user ("$1$3"));

/* The following should be rewritten when MX-record versions of  */
/* sendmail exist. */

/* Now,to see if a host is UUCP or TCP, we use a gross hack: */
/* a.b.c. resolves to a.b.c if a.b.c is a valid TCP host */
/* Note that this is doomed to failure if the canonicalization */
/* returns a "soft" failure.  To reduce the chance that we'll get  */
/* screwed by flakey name servers, we try twice. */
/* Sendmail SHOULD just drop the message back into the queue if  */
/* it gets a soft NS failure on the expand. */

/* A better way would be to use a version of sendmail which understands */
/* MX mail forwarding records. */

	if ( anypath <@ hostpath > anypath )	/* canonicalize */
		next ($1<@canon ($2)>$3);
	if ( anypath <@ hostpath > anypath )	/* check with . */
		next ($1<@canon ($2.)>$3);

/* let's see if it resolved (Kludge alert!) */
	if ( anypath <@ hostpath .> anypath )	/* Nope, try it again... */
		next ($1<@canon ($2.)>$3);

/* Now we are fairly confident (well, sort of) */
	if ( anypath <@ hostpath .> anypath )	/* Nope, assume UUCP */
		resolve (mailer (uucp),
				host ($2),
				user ("$1$3"));
	if ( anypath <@ hostpath > anypath )	/* It resolved, use tcp */
		resolve (mailer (tcp),
				host ($2),
				user ("$1<@$2>$3"));

	if (| one_or_more )	/* Program execution here */
		resolve (mailer (local),
				user (|$1));

#ifdef LOCALUSERS
	if ( localuser )		/* Local users here */
		resolve (mailer (local),
				user ($1));
	if ( localuser <> zero_or_more )
		resolve (mailer (local),
				user ($1));
#endif
#ifdef MAILHUB
	/* Send everything else to a mailhub */
	if ( usr )
		resolve (mailer (tcp),
				host ($mailhub),
				user ($1));
#else
	/* everything else must be a local name */
	if ( usr )	/* local names */
		resolve (mailer (local),
				user ("$1"));
#endif
	}

/* ############################################################ */
/* ############################################################ */
/* ##### */
/* #####		Local and Program Mailer specification */
/* ##### */
/* #####		@(#)localm.m4	4.1		7/25/83 */
/* ##### */
/* ############################################################ */
/* ############################################################ */

mailer
	local {
		Path = "/bin/mail",
		Flags = { f_rfrom, f_locm, f_strip, f_date, f_from,
				  f_mesg, f_mult, f_noufrom },
		Sender = MAGIC_RW,
		Recipient = UNIMPLEMENTED,
		Argv = "mail -d ${m_ruser}"
	};
mailer
	prog {
		Path = "/bin/sh",
		Flags = { f_locm, f_strip, f_date, f_from,
				  f_mesg, f_expensive },
		Sender = MAGIC_RW,
		Recipient = UNIMPLEMENTED,
		Argv = "sh -c ${m_ruser}"
	};

ruleset
	MAGIC_RW {
	if (@)	
		retry ("MAILER"-"DAEMON");	/* errors to mailer-daemon */
	}

/* ############################################################ */
/* ############################################################ */
/* ##### */
/* #####		UUCP Mailer specification */
/* ##### */
/* #####		@(#)uucpm.m4	4.2		8/30/83 */
/* ##### */
/* ############################################################ */
/* ############################################################ */


mailer
	uucp {
		Path = "/bin/smail",
		Flags = { f_strip, f_date, f_from, f_mesg,
				  f_upperh, f_upperu, f_mult },
		Sender = UUCP_SENDER_RW,
		Recipient = UUCP_RECIPIENT_RW,
		Maxsize = "100000",
		Argv = "smail -r -vH${m_oname} ${m_rhost}!${m_ruser}"
	};

ruleset
	UUCP_SENDER_RW {
/* Remove internal uucp syntax marker */
	if ( usr <@ hostname ."UUCPS"> anypath )	
		retry ($2!$1$3);		/* u@h.UUCPS => h!u */

	if ( anypath <@ chaoshost > anypath )
		return (<@$m_oname:$1@$2>$3);
	if ( anypath <@ chaoshost . domain > anypath )
		return (<@$m_oname:$1@$2.$3>$4);
	if ( anypath <@ hostpath > anypath )	/* already ok */
		return ($1<@$2>$3);
	if ( hostpath )	/* tack on our full address */
		return ($1<@$m_oname>);

	}
ruleset
	UUCP_RECIPIENT_RW {
	/* Remove internal uucp syntax marker */
	if ( usr <@ hostname ."UUCPS"> anypath )
		retry ($2!$1$3);		/* u@h.UUCPS => h!u */


#ifdef notdef
/* Non domain specified names assume to be on parent domain */
	if ( anypath <@ hostname > anypath )
		return ($1<@$2.$D>$3);
#endif
	}

/*
 * Rewrite sender and recipient address to deal with localusers and mailhubs.
 * Also make sure that naked address don't happen.
 */

ruleset
	LOCALUSER_RW {
	if ( username )	
		retry ($1<@$m_sitename.$D>); /* No naked addresses! */
	if ( username <@ this_host> anypath)
		retry ($1<@$m_sitename.$D>$3); /* Deal with undominified 
						name */
#ifdef MAILHUB
#ifdef LOCALUSERS
	if ( localuser <@ this_host .$D> anypath)
		return ($1<@$m_sitename.$D>$3);
#endif
	if ( usr <@ this_host .$D> anypath )
		return ($1<@$mailhub>$3);
#endif
	}

/* 
 *	Arpanet TCP Mailer specification
 *
 *	@(#)tcpm.m4	4.1		7/25/83
 */

mailer
	tcp {
		Path = "[IPC]",
		Flags = { f_mult, f_strip, f_date, f_from, f_mesg,
				  f_upperu, f_expensive, f_dot, f_llimit },
		Sender = TCP_SENDER_RW,
		Recipient = TCP_RECIPIENT_RW,
		Argv = "IPC ${m_rhost}",
		Eol = "\r\n"
	};

ruleset
	TCP_SENDER_RW {
	if ( anypath )
		next (LOCALUSER_RW($1));
	if ( anypath <@ hostname ."UUCPS"> anypath )
		return ($2!$1<@$m_oname>$3);	/* UUCP --> path@domain */
	if ( username )
		return ($1@$m_oname);	/* Local user --> (user@domain) */
	if ( anypath <@ hostname > anypath )
		/* Non domain specified names assumed to be on our
		 * parent domain */
		return ($1<@$2.$D>$3);
	if ( anypath <@ hostname > anypath )
		/* Domain named machines are unchanged. */
		return ($1<@$2>$3);
	if ( anypath < anypath > anypath )
		/* Give us as the path for any other address. */
		retry ($1$2$3);
	if ( hostname )
		return (<@$m_oname:$1>);
	}

ruleset
	TCP_RECIPIENT_RW {
	if ( anypath )
		return (LOCALUSER_RW($1));
	if ( one_or_more )	/* Noop rule */
		return ($1);
	}
