/*
 * athena.ease --- Athena.mit.edu's sendmail file, translated into ease.
 * 
 */

/*************************************************************/
/*
 * 
 *		SENDMAIL CONFIGURATION FILE
 * 
 * Standard configuration file for all hosts running 4.3+NFS UNIX
 * 
 *  Mark L. Lambert (markl@PTT.LCS.MIT.EDU) 
 * 
 * Revision history:
 *
 * Tue Mar  5 23:20:00 1991 Theodore Ts'o (tytso at mit)
 * 	* Recast the file into ease format, and added generalizations for
 * 	various different types of hosts.
 * 
 * Mon Oct 23 12:00:00 1989 Ron Hoffmann (hoffmann at bitsy) 
 * 	* Commented out special case for MITVMC, now IP-live
 * 
 * Fri Sep 22 14:35:00 1989 Stan Zanarotti (srz at mit)
 *	* Fixed up to work on Athena.mit.edu, removed
 *	  chaosnet & tcpmit commented code.
 * 
 * Thu May 25 18:00:00 1989 Stan Zanarotti (srz at mit) 
 * 	* Added in rules for Pop mailer 
 * 
 * Thu May 25 16:00:00 1989 Stan Zanarotti (srz at athena) 
 *	* Commented out references to Chaosnet, to simplify life.
 * 	  Also, DECNET should be taken care of by MX records.
 * 
 * Thu Nov  5 17:00:00 1987 Mark L. Lambert (markl at allspice) 
 *       * in ruleset 6, only those hosts in the chaosonly (O) class 
 *         have the .CHAOS suffix added.  It's a temporary hack so that 
 *         chaos/IP hosts will get mail sent to them via TCP/SMTP rather 
 *         than CHAOS MAIL.  This until we find out why the chaos MAIL server 
 *         code doesn't work on our 4.3 distribution...
 * 
 * Tue Nov  3 15:40:02 1987 Mark L. Lambert (markl at allspice) 
 * 	* all outgoing mail has ptt.lcs.mit.edu as our host name,
 * 	  rather than allspice.lcs.mit.edu 
 *
 * Sun Nov  1                Tim Shepard (shep at allspice) 
 *       * added PTT to list of allspice's synonyms. 
 * 
 * Fri Oct 30 12:06:51 1987  Mark L. Lambert  (markl at allspice)
 *	* hacked ruleset 3 so that addresses of the form "markl"
 *	  are rewritten to be "markl@allspice.lcs.mit.edu".  Tim
 *	  likes *all* his addresses fully qualified, even local ones...
 * 
 * Tue Oct 13 10:25:30 1987  Mark L. Lambert  (markl at allspice)
 *	* fixed csnet and dec mail relay code to strip .CSNET and
 *	  .DEC internal suffixes from addresses 
 * 
 * Tue Sep  8 12:26:59 1987  Mark L. Lambert  (markl at allspice) 
 *	* fixed TCP mailer S11/21 S13/23 bug where foo<@LOCAL> was
 *	  being treated like a single host token and getting
 *	  the domain tacked on.  Since local domain appending was
 *	  already being done in R6 in the name canonicalization call,
 *	  local domain appending has been eliminated from S11/21 and
 *         S13/23 
 * 
 * Mon Aug 24 17:32:08 1987  Mark Lambert  (markl at thyme) 
 *	* removed .CHAOSENVELOPE hack.  chaos MAIL accepts
 *         user@host just fine.  It does *not* accept source routed
 *	  addresses, so I've written rules to rewrite simple source
 *	  routes in terms CHAOS can understand, and disallow complex
 *	  source routes.  Also removed R3 conversion from
 *	  random ancient address formats to canonical.  We
 *	  aren't Berkeley, and the conversion might trip us
 *	  up some day when we aren't expecting it.
 * 
 * Fri Aug 21 18:03:38 1987  Mark Lambert  (markl at thyme) 
 * 	* installed
 */

/*************************************************************/

/*
 * Very Useful Information I Wish I Had When I First Touched This
 * Config File:
 * 
 *  I. A message has two parts, an "envelope", containing delivery
 * instructions for the mail protocol, and a "body" containing the
 * message header and text.  Sendmail modifies mail addresses in both
 * the envelope and the body.  Some rewriting rulesets will apply to
 * envelope addresses and others to body addresses.  Some rulesets
 * will apply to sender addresses (envelope and body) and others to
 * recipient addresses (also envelope and body) still other rulesets
 * will apply to all addresses, envelope or body, recipient or
 * sender..  It is important to remember that the envelope addresses,
 * being delivery instructions, are never seen by the user.  It is
 * also important to remember that the addresses in the body will be
 * used by the user to contruct replies or forwards.
 *
 * II. Addresses will continually be referred to by classifications.
 * There are "sender" addresses and "recipient" addresses.  Addresses
 * are defined as sender or receiver depending on:
 * 
 *  	1. context (i.e. a sendmail command line arg that is not a
 * 	switch is a recipient)
 * 
 * 	2. the field the address appears in.  In this case, fields are 
 * 	typed as sender/receiver in a data structure defined in conf.c
 * 
 * III: each envelope sender and recipient address takes the following path:
 * 
 *    S3 -> S0 (results in a <MAILER,HOST,USER> triple) 
 *    USER then travels S2 -> S<MAILER's recipient rewriting ruleset> -> S4 
 * 
 *  II: each body sender address takes the following path: 
 * 
 *    R3 -> R1 -> R<MAILER's sender rewriting ruleset> -> R4 
 * 
 * III: each body recipient address takes the following path: 
 * 
 *    R3 -> R2 -> R<MAILER's recipient rewriting ruleset> -> R4 
 * 
 * IV. each mailer's sender and recipient rewriting rulesets are set in 
 *     that mailer's definition 
 * 
 *	i.e. "Mtcp, P=[IPC], F=mDFMueXLC, S=14, R=24, A=IPC $h, E=\r\n" 
 *					    ^^    ^^
 */

/*************************************************************/

/*   Machine-dependent setup information */

/*************************************************************/

/* This is for watch's entry */
#define WATCH_COM

#define CSNET_RELAY	"RELAY.CS.NET"
#define BITNET_RELAY	"MITVMA.MIT.EDU"
#define UUCP_RELAY	"BLOOM-BEACON.MIT.EDU"

#define MY_IP_ADDR	"18.72.0.39"
#define MY_UUCP_NAME	"mit-athena"
#define MY_DOMAIN	"MIT.EDU"

/* Turns on hacks specific for ATHENA.MIT.EDU */
#define ATHENA_MIT_EDU
#define LOCALHOSTS	"/usr/lib/localhosts"

#ifdef TSX			/* For Ted's workstation */
#define MAILHUB 	"ATHENA.MIT.EDU"
#define LOCALUSERS	"/site/usr/lib/localusers"
#undef MY_IP_ADDR
#define MY_IP_ADDR	"18.72.0.51"
#undef MY_UUCP_NAME
#undef LOCALHOSTS
#define LOCALHOSTS "/site/usr/lib/localhosts"
#undef ATHENA_MIT_EDU
#define VERSION_IN_HEADER
#endif

#ifdef WATCH_COM
#undef MY_IP_ADDR
#define MY_IP_ADDR	"133.244.0.2"
#undef MY_UUCP_NAME
#undef ATHENA_MIT_EDU
#undef LOCALHOSTS
#define VERSION_IN_HEADER
#undef CSNET_RELAY
#define CSNET_RELAY	"TSX-11.MIT.EDU"
#undef BITNET_RELAY
#define BITNET_RELAY	"TSX-11.MIT.EDU"
#undef MY_DOMAIN
#define MY_DOMAIN	"WATCH.COM"
#endif

/*
 * All the names I am known by.  Substitute your host name and any aliases. 
 * don't add aliases of the form Foo.LCS.MIT.EDU or Foo.ARPA, since the config 
 * pattern-matching code doesn't match multiple-token class entries.  There 
 * are rewrite rules which do this for you automagically.  Trust me.
 */

class
#ifdef WATCH_COM
	c_myname = { "WATCH", IPSWICH, "IPSWICH-SL" };
#else
#ifdef TSX
	asm("CwTSX-11 TSX");
#else
	c_myname = { ATHENA, "MIT-ATHENA" };
#endif
#endif

/*
 *  My IP address: this allows my sendmail to recognize an address of the form 
 * "markl@[18.26.0.115]" as being local, and routing mail to it through the 
 * "local" mailer.  Otherwise, it would route through another mailer, which 
 * would probably refuse to establish a connection to itself.
 */

macro
	I = MY_IP_ADDR;

/*************************************************************/
/*
 * Setup Information
 */
/*************************************************************/

/*************************************************************/
/*
 *   Private Macros
 */
/*************************************************************/

macro
	D = MY_DOMAIN;		/* My domain.  Substitute yours as necessary */
#ifdef BITNET_RELAY
	C = BITNET_RELAY;		/* bitnet relay */
#endif
#ifdef CSNET_RELAY
	E = CSNET_RELAY;		/* CSNET relay */
#endif
#ifdef UUCP_RELAY
	P = UUCP_RELAY;			/* UUCP relay */
#endif
#ifdef MY_UUCP_NAME
	U = MY_UUCP_NAME;		/* UUCP name */
#endif
#ifdef MAILHUB
	M = MAILHUB;
#endif

/* my official hostname.  All outgoing mail from this machine will have */
/* this address appended, regardless of what the host's real name is. */
/* Default to $w (host's canonical name) + local domain */
	m_oname = "${m_sitename}";

/*************************************************************/
/*
 *   Private classes
 */
/**************************************************************/

/* Athena local hosts.  These are Athena servers that have out of date */
/* config files.  We may have to deal with things sent to these hosts */
/* ourselves. */
class
#ifdef LOCALHOSTS
	S = readclass (LOCALHOSTS);
#endif
#ifdef LOCALUSERS
	localusers = readclass(LOCALUSERS);
#endif

/* POP support.  Name used in pop aliases. */
/* Define a macro & class just to be flexible. */
	P = { pop };

/* Internal domains */
	T = { LOCAL, UUCP, BITNET, CSNET, CHAOS };


/*************************************************************/

/*   Config file version number */

/*************************************************************/

macro
	V = "1.2";


/*************************************************************/

/*   Special macros */

/*************************************************************/

/*
 * definitions for each macro appear in the manual.  Just in case 
 * you are foolish enough to hack this file without benefit of a manual 
 * (sort of like hacking MG auto wiring without a Lucas wiring diagram), 
 * some definitions follow as well.  Macros are defined by:
 * 
 *	 D<macro-letter><definition>
 */

macro
	m_daemon = "MAILER-DAEMON";	/* My name */

	/* stupid losing brain-dead pinheaded UNIX-style from field */
	m_ufrom = "From ${m_sreladdr}  ${m_udate}";

	m_addrops = ".:%@!^=/[]";	/* token delimiting characters */

/* format of sender's address */
	m_defaddr = concat ("${m_sreladdr}", ifset (m_sname, " (${m_sname})"));

/* SMTP greeting message */
	m_smtp = "${m_oname} Sendmail\", or BOBO?\" ${m_version}/${V} ready at ${m_adate}";

/*************************************************************/
/*
 *  Options
 */
/*************************************************************/
/*
 * options are also defined in the manual.  Short explanations appear here 
 * for the faint of heart
 */

options
	o_alias = "/usr/lib/aliases";	/* location of alias file */
	o_ewait = "10";	/* wait up to ten minutes for alias file rebuild */
	o_bsub = ".";	/* substitution for space (blank) characters */
#ifdef notdef
	o_qwait = "";	/* (don't) connect to "expensive" mailers */
#endif
	o_delivery = d_background;	/* default delivery mode */
	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_rsend = "";			/* Send mail to self even in aliases */
	o_hformat = "";			/* default messages to old style */
	o_qdir = "/usr/spool/mqueue";	/* queue directory */
	o_tread = "2h";			/* read timeout.  This */
					/* violates most mail */
					/* protocols.  Since when has */
					/* sendmail cared about that? */ 
	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) */
#ifdef notdef
	o_dmuid = "1";			/* default UID */
#endif
	o_wizpass = "*";		/* wizard's password */
	o_loadq = "12";	/* load average at which we just queue messages */
	o_loadnc = "10"; /* load average at which we refuse connections */

#ifdef notdef
	o_newproc = "";	/* Fork separate process for each queue request */
#endif

/*************************************************************/
/*
 * Message precedences
 */
/*************************************************************/

precedence
	first-class = 0;
	special-delivery = 100;
	bulk = -60;
	junk = -100;

/*************************************************************/
/*
 * Trusted users
 */
/*************************************************************/

trusted
	{ root };
	{ daemon};
	{ uucp};
	{ network };

/*************************************************************/
/*
 * Format of various header fields.
 */
/*************************************************************/

/*
 * Note that different mail domains may want or not want these fields, 
 * and may or may not overwrite them if they are already present in a message 
 * body.  Behaviour is defined in conf.c  Note that some of the macros 
 * in these expressions are not defined in the config file.  Instead they 
 * are definied on the command line to sendmail using the "-oM<name><val>" 
 * option.  This is how CHAOS MAIL and SMTP servers relay the protocol 
 * name, sending host name, and network name to sendmail for placement 
 * in the message's received: line.
 */

header
	for (f_return) {
		define ("Return-Path:", "<${m_sreladdr}>");
	};

	define ("Received:", 
		concat (ifset (m_shostname, "from ${m_shostname} "), 
			"by ${m_oname} "),
#ifdef ATHENA_MIT_EDU
		concat (ifset (Q, "via ${Q} "), ""),
#endif
		concat (ifset (m_protocol, "with ${m_protocol}"),
			"\
"),
#ifdef VERSION_IN_HEADER
		"with sendmail-${m_version}/${V}, ",
#endif
		"id ${m_qid}; ${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:", "");

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


/*************************************************************/
/*
 * Rewriting Rules
 */
/*************************************************************/

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_9 = ruleset 9;
	LOCAL_SENDER_RW = ruleset 10;
	TCP_SENDER_RW = ruleset 11;
	POP_SENDER_RW = ruleset 17;
	POP_RECIPIENT_RW = ruleset 18;
	LOCAL_RECIPIENT_RW = ruleset 20;
	TCP_RECIPIENT_RW = ruleset 21;
#ifdef MY_UUCP_NAME
	TO_OLDSTYLE = ruleset 5;
	UUCP_SENDER_RW = ruleset 14;
	UUCP_RECIPIENT_RW = ruleset 24;
#endif

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

        anypath                 : match (0*);
	path, usr, hostpath	: match (1*);
        domain                  : match (1*);
        username, hostname	: match (1);

	this_host : match (1) in c_myname;
	internal_domain : match (1) in T;
	not_internal_domain : match (0) in T;
#ifdef LOCALHOSTS
	localhosts : match (1) in S;
#endif
	POP : match (1) in P;
#ifdef LOCALUSERS
	localuser		: match (1) in localusers;
	not_localuser		: match (0) in localusers;
#endif

/*************************************************************/
/*
 * Sender Field Pre-rewriting
 */
/*************************************************************/

/* Nope, uh uh, no rewriting rules here... */

ruleset
	SENDER_PREWRITE {

	}

/*************************************************************/
/*
 * Recipient Field Pre-rewriting
 */
/*************************************************************/

/* not here either... */
ruleset
	RECIPIENT_PREWRITE {

	}

/*************************************************************/
/*
 *  Final Output Post-rewriting.  All, count themm, ALL, 
 *  addresses get run through this ruleset.
 */
/*************************************************************/

/*
 * 
 * here we do the following: 
 * 
 * I. remove focussing brackets from the address 
 * 
 * II. Replace "LOCAL" hostname with our official host name $j 
 * 
 * III. Fix up source-routed addresses that had commas switched to colons. 
 * 
 * IV. Remove CHAOS domain from chaos hostnames 
 * 
 * V. Convert UUCP addresses from foo@bar.DOMAIN.UUCP to bar.DOMAIN!foo 
 * 
 * VI. Look for duplicate local hostnames and replace with single hostname
 */

ruleset
	FINAL_POSTWRITE {

	if (@)	
		return ();		/* handle <> error addr */

	if ( anypath < path > anypath )
		retry ($1$2$3);			/* defocus */
	if ( zero_or_more @"LOCAL" zero_or_more )
		retry ($1@$m_oname$2);		/* subst my host name */
	if (@path: @path: usr )	/* <route-addr> fixup */
		retry (@$1,@$2:$3);
	
/*R$*@$+.CHAOS$*		$1@$2$3				CHAOS fixup */

/*
 * UUCP must always be presented in "!" form (with domains, leave
 * the ".uucp")
 */ 
#ifdef MY_UUCP_NAME
	if ( usr @$m_oname."UUCP")
		retry ($U!$1);
#endif
	if ( usr @ hostname ."UUCP")
		retry ($2!$1);
	if ( one_or_more @ exactly_one . exactly_one ."UUCP")
		retry ($2.$3."uucp"!$1);
	if ( one_or_more @ exactly_one . exactly_one . exactly_one ."UUCP")
		retry ($2.$3.$4."uucp"!$1);
	if ( one_or_more @ exactly_one . exactly_one . exactly_one . exactly_one ."UUCP")
		retry ($2.$3.$4.$5."uucp"!$1);
	if ( one_or_more @ exactly_one . exactly_one . exactly_one . exactly_one . exactly_one ."UUCP")
		retry ($2.$3.$4.$5.$6."uucp"!$1);

/* delete duplicate local names */
	if ( usr % this_host @$m_oname)
		retry ($1@$m_oname);
	if ( usr % this_host ."ARPA"@$m_oname)
		retry ($1@$m_oname);
	if ( usr % this_host . internal_domain @$m_oname)
		retry ($1@$m_oname);
	if ( usr % this_host .$D@$m_oname)
		retry ($1@$m_oname);
	}

/*************************************************************/
/*
 *  Name Canonicalization, a.k.a. ruleset 3.  This ruleset has 
 *  the terrible burden of converting addresses of all flavors 
 *  into one standard form.  One form to rule them all, one 
 *  form to find them, one form to bring them all and in the 
 *  darkness rewrite the hell out of them... 
 */
/*************************************************************/

ruleset
	NAME_CANON {

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

/* basic textual canonicalization -- note RFC733 heuristic here */
/* ("RFC 733? What is that?" you cry.  I surely don't know...) */

	if ( anypath < anypath < anypath < path > anypath > anypath > anypath )
		retry ($4);		/* 3-level <> nesting */
	if ( anypath < anypath < path > anypath > anypath )
		retry ($3);		/* 2-level <> nesting */
	if ( anypath < path > anypath )	
		retry ($2);	       /* basic RFC822 parsing */

	/* the ghost of MULTICS still haunts us, even today */
	if ( usr " at " path )
		retry ($1@$2);

/* make sure <@a,@b,@c:user@d> syntax is easy to parse -- undone later */
	if (@path , usr )	/* change all "," to ":" */
		retry (@$1:$2);
/*
 * handle source-routed addresses by focussing on the host.domain and 
 * handing it to ruleset 6 for cleanup
 */
	if (@path: usr )
		return (LOCAL_RW (<@$1>:$2));

/*
 * handle mailing lists by ignoring them.  Sendmail's address-parsing 
 * code screws them up anyway:
 * 
 *  you ask sendmail to deliver to: "foobar:markl, shep, srz;" 
 * 
 *  sendmail delivers to: "foobar:markl", "shep", "srz;" 
 * 
 * lovely, huh?
 */
	if ( one_or_more : zero_or_more ;@ one_or_more )
		return ($1:$2;@$3);
	if ( one_or_more : zero_or_more ;)
		return ($1:$2;);
/*
 * focus on the "host.domain" part of the address. 
 * if there is more than one host (markl@foo@bar), 
 * focus on the last host
 */
	if ( usr @ domain )	/* focus on domain */
		next ($1<@$2>);
	if ( path < path @ domain >)	/* move gaze to last host */
		next ($1$2<@$3>);

/*
 * add local host name to single-token address.  i.e. "markl" becomes 
 * "markl@allspice.lcs.mit.edu".
 */
#ifdef MAILHUB
#ifdef LOCALUSERS
	if ( localuser )
		retry ($1<@$m_oname>);
#endif
	if ( username )
		retry ($1<@$M>);
#else
	if ( username )
		retry ($1<@$m_oname>);
#endif

/*
 * if its already canonical, send it to ruleset 6 for cleanup and leave
 */
	if ( one_or_more <@ one_or_more >)
		return (LOCAL_RW ($1<@$2>));

/*
 * otherwise canonicalize the address, converting from arbitrary
 * formats to a user<@host.domain> format
 */
	if ( username ! hostpath )	/* convert uucp */
		return (LOCAL_RW ($2<@$1."UUCP">));
	if ( path . username ! hostpath )	/* and domain uucps */
		return (LOCAL_RW ($3<@$1.$2>));
	if ( path ! path )	/* and subdomain uucps */
		return (LOCAL_RW ($2<@$1."UUCP">));
	if ( usr % hostpath )	/* user%host */
		next (RULESET_9 ($1%$2));
	if ( usr <@ hostpath >)	/* already canonical */
		return (LOCAL_RW ($1<@$2>));
	}

/*************************************************************/
/*
 * special local conversions
 */
/*************************************************************/

/*
 * here, we convert the following to the hostname LOCAL: 
 * 
 * I. our IP address in brackets (i.e. markl@[18.26.0.115]) 
 * 
 * II: our name or any of our aliases 
 * 
 * III: any perversions of our name or its aliases (i.e. markl@allspice.arpa, 
 *      markl@allspice.uucp, markl@allspice.lcs.mit.edu) 
 * 
 * IV: the name of all machines that are local (sending to them is 
 *      equivalent to sending to us).
 */

ruleset
	LOCAL_RW {
	
/*
 * If we have are doing the mailhub game, then we need to make sure
 * that the addresses reflect the mailhub, and not our own host,
 * unless it's a local user.
 *
 * Note that non_localuser@localhost.LOCAL will go to the local
 * mailer; this is considered a feature.
 */
#ifdef MAILHUB
#ifdef LOCALUSERS
	if ( not_localuser <@ this_host > anypath )
		retry ( $1<@$M>$3 );
	if ( not_localuser <@ this_host . $D > anypath )
		retry ( $1<@$M>$3 );
#else
	if ( username <@ this_host > anypath )
		retry ( $1<@$M>$3 );
	if ( username <@ this_host . $D > anypath )
		retry ( $1<@$M>$3 );
#endif
#endif

	/* local hostname conversion */
	if ( zero_or_more <@[$I]> zero_or_more )	/* local IP addr */
		next ($1<@"LOCAL">$2 );
	if ( zero_or_more <@ this_host > zero_or_more )	/* aliases */
		next ($1<@"LOCAL">$3 );
#ifdef LOCALHOSTS
	if ( zero_or_more <@ localhosts > zero_or_more )	/* localhosts */
		next ($1<@"LOCAL">$3);
#endif
	if ( zero_or_more <@ this_host ."ARPA"> zero_or_more )	/* aliases.ARPA */
		next ($1<@"LOCAL">$3);
	if ( zero_or_more <@ this_host . internal_domain > zero_or_more )	/* aliases.UUCP */
		next ($1<@"LOCAL">$4);
	if ( zero_or_more <@ this_host .$D> zero_or_more )	/* aliases.MIT.EDU */
		next ($1<@"LOCAL">$3);
#ifdef WATCH_COM
	if ( zero_or_more <@ "WATCH.COM"> zero_or_more )
		next ($1<@"LOCAL">$2);
#endif
#ifdef LOCALHOSTS
	if ( zero_or_more <@ localhosts .$D> zero_or_more )	/* localhosts.MIT.EDU */
		next ($1<@"LOCAL">$3);
#endif
	if ( one_or_more <@"LOCAL">)	/* and return */
		return ($1<@"LOCAL">);
/*
 * any vicious rumors to the contrary, local names should *not* always be 
 * stripped out of the front of source-routed addresses.  The only place 
 * they should be stripped is in ruleset zero.  Thus, return source-routed 
 * addresses unmarked by the ravages of stripping...
 */
	if (<@"LOCAL">: one_or_more )
		return (<@"LOCAL">:$1);

/*
 * check to see if the host should be run through the nameserver.  Don't 
 * resolve via the nameserver if the host has an internal domain tacked 
 * on.  Do resolve hosts with other domains tacked on.  Do resolve 
 * hostnames without domains, by first tacking on our local domain. 
 * First, we make sure that pop doesn't get ground through the domain server.
 */
	if ( anypath <@ POP > anypath )
		return ($1<@$2>$3);
	if ( anypath <@ anypath . not_internal_domain > anypath )
		return ($1<@ canon ($2.$3)>$4);
	if ( anypath <@ hostname > anypath )
		return ($1<@ canon ($2.$D)>$3);
	}

/*************************************************************/
/*
 * Change rightmost % to @
 */
/*************************************************************/

ruleset
	RULESET_9 {
	if ( zero_or_more % zero_or_more )	/* First make them all @s. */
		retry ($1@$2);
	if ( zero_or_more @ zero_or_more @ zero_or_more )	/* Undo all but the last. */
		retry ($1%$2@$3);
	if ( zero_or_more @ zero_or_more )	/* Put back the brackets. */
		return ($1<@$2>);
	}


/*************************************************************/
/*
 *   Mailer definitions, one for each mail domain that we support 
 *   (chaos, uucp, and tcp are always popular examples...)
 */
/*************************************************************/

/*************************************************************/
/*
 * Local and Program Mailer specification
 */
/*************************************************************/

mailer
	local {
		Path = "/bin/mail",
		Flags = { f_rfrom, f_locm, f_strip, f_date, f_from, 
			f_mesg, f_mult, f_noufrom },
		Sender = LOCAL_SENDER_RW,
		Recipient = LOCAL_RECIPIENT_RW,
		Argv = "mail -d ${m_ruser}"
	};

mailer
	prog {
		Path = "/bin/sh",
		Flags = { f_locm, f_strip, f_date, f_from, 
					f_mesg, f_expensive },
		Sender = LOCAL_SENDER_RW,
		Recipient = LOCAL_RECIPIENT_RW,
		Argv = "sh -c ${m_ruser}"
	};

ruleset
	LOCAL_SENDER_RW {
	if (@)	/* errors to mailer-daemon */
		retry ($m_daemon);
	}

ruleset
	LOCAL_RECIPIENT_RW {
	}


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

/******************************************************/
/*  General code to convert back to old style names  **/
/******************************************************/

ruleset
	TO_OLDSTYLE {

	if ( usr <@ hostname ."UUCP">)	/* u@host.UUCP => host!u */
		retry ($2!$1);
	if ( usr <@"LOCAL">)	/* u@LOCAL => u */
		retry ($1);
	if ( usr @ hostpath ."ARPA")	/* u@host.ARPA => u@host */
		retry ($1@$2);
	}


mailer
	uucp {
		Path = "/usr/bin/uux",
		Flags = { f_strip, f_date, f_from, f_mesg, f_upperh,
				  f_upperu, f_ufrom },
		Sender = UUCP_SENDER_RW,
		Recipient = UUCP_RECIPIENT_RW,
		Maxsize = "100000",
		Argv = "uux - -r -z -a${m_saddr} -gC ${m_rhost}!rmail (${m_ruser})"
	};

ruleset
	UUCP_SENDER_RW {
	if ( one_or_more )	/* convert to old style */
		next (TO_OLDSTYLE ($1));
	if ( this_host ! one_or_more )	/* strip local name */
		retry ($2);
	if ( zero_or_more <@ exactly_one > zero_or_more )	/* resolve abbreviations */
		retry ($1<@$2."ARPA">$3);
	if ( one_or_more )	/* stick on our host name */
		next ($U!$1);
	}

ruleset
	UUCP_RECIPIENT_RW {
	if ( zero_or_more <@ one_or_more ."UUCP"> zero_or_more )
		return ($1<@$2."UUCP">$3);
	if ( zero_or_more <@ exactly_one > zero_or_more )
		return ($1<@$2."UUCP">$3);
	}
#endif /* MY_UUCP_NAME */

/*************************************************************/
/*************************************************************/
/******/
/*****           MH POP mailer specification */
/******/
/*****           @(#)popMH.m4    4.1     05/15/85 */
/******/
/*************************************************************/
/*************************************************************/

mailer
	pop {
		Path = "/bin/spop",
		Flags = { f_noufrom, f_strip, f_mult, f_from, f_date, f_mesg },
		Sender = POP_SENDER_RW,
		Recipient = POP_RECIPIENT_RW,
		Argv = "pop ${m_ruser}"
	};

ruleset
	POP_SENDER_RW {
	if (@)	/* errors to mailer-daemon */
		retry ("MAILER"-"DAEMON");
	if ( one_or_more )	/* null rule */
		return ($1);

	}
ruleset
	POP_RECIPIENT_RW {

	if ( one_or_more )	/* null rule */
		return ($1);
	}

/*************************************************************/

/*	TCP/SMTP Mailer specification */

/*************************************************************/

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

/*
 * this ruleset is called on all sender addresses in the message header of
 * a message being delivered to a TCP/SMTP mailer
 */

ruleset
	TCP_SENDER_RW {

/* pass <route-addr>'s through unscathed */
	if (<@ one_or_more >: zero_or_more )
		return (<@$1>:$2);

/* For addresses of the form USER, add our host name */
	if ( exactly_one )
		return ($1<@$m_oname>);

/* everything else left unchanged */
	if ( zero_or_more <@ one_or_more > zero_or_more )
		return ($1<@$2>$3);

	}

/*
 * this ruleset is called on: 
 * 
 * I.  all recipient addresses in the body of a message being
 *     delivered to a TCP/SMTP mailer
 * 
 * II. all recipient addresses in the envelope of a message being
 *     delivered to a TCP/SMTP mailer
 * 
 * rewriting rules are as above...
 */

ruleset
	TCP_RECIPIENT_RW {

	if (<@ one_or_more >: zero_or_more )
		return (<@ canon ($1)>:$2);
	if ( username )
		return ($1<@$m_oname>);
	if ( zero_or_more <@ one_or_more > zero_or_more )
		return ($1<@$2>$3);
	}

/*************************************************************/
/*
 * Ruleset Zero
 */
/*************************************************************/

/*************************************************************/
/*
 * 		RULESET ZERO PREAMBLE
 * 
 *	The beginning of ruleset zero is constant through all
 *	configurations.
 */
/*************************************************************/

/*
 * Here's the plan:
 * 
 * I. Remove focussing brackets from around the hostname, in case this is 
 *    is a recursive call to R0 
 * 
 * II. Canonicalize the address using R3 
 * 
 * III. Route IP-addressed mail specially 
 * 
 * IV. Route local mail to the local mailer 
 * 
 * V. Route error mail to the mailer daemon 
 * 
 * VI. Strip off local hostnames that made it through 
 *     the first attempt to route to the local mailer and 
 *     run them through R0 again, in the hope that they 
 *     will simplify.
 */

ruleset
	BASE_RW {

	if ( zero_or_more < zero_or_more > zero_or_more )	/* defocus */
		retry ($1$2$3);
	if ( one_or_more )	/* canonicalize */
		next (NAME_CANON ($1));

/* deal with mail of the form markl@[18.26.0.115] */
	if ( zero_or_more <@[ one_or_more ]> zero_or_more )
		resolve (mailer (tcp),
				host ([$2]),
				user ($1@[$2]$3));

/* deal with mail of the form markl@LOCAL */
	if ( username <@"LOCAL">)	/* local mail */
		resolve (mailer (local),
				user ($1));

/* deal with error mail (mail to "@") */
	if (@)	/* handle <> form */
		resolve (mailer (local),
				user ($m_daemon));

/*
 * handle .LOCAL's, by sending them to the given host, no questions
 * asked.
 */
	/* Send it on */
	if ( zero_or_more <@ zero_or_more ."LOCAL"> zero_or_more )
		resolve (mailer (tcp),	
				host ($2.MIT.EDU),
				user ($1<@$2. "LOCAL" >$3));

/* now delete the local info */
	if ( zero_or_more < zero_or_more "LOCAL"> zero_or_more )	
		retry ($1<$2>$3);	/* punt local host */
	if ( zero_or_more < zero_or_more .> zero_or_more )	
		retry ($1<$2>$3);	/* drop trailing dot (??) */

/* if a source route, punt the local host from the route and retry */
	if (<@>: zero_or_more )
		return (BASE_RW ($1));

/* if another address (i.e. foo%bar@LOCAL), strip the LOCAL and retry */
	if ( zero_or_more <@>)
		return (BASE_RW ($1));

/*
 * Based on its internal domain name, route our message to 
 * the proper mailer.  Note that most internal domains resolve 
 * to the TCP mailer; their only special treatment is to be routed 
 * to a relay host first. 
 * 
 * Note that $@ on the RHS refers to a host, and $: to a user.  This 
 * is only true in an RHS beginning with $# (see manual for justification 
 * of this silliness).
 */

	/* Sendmail addressed to "pop" via the pop mailer. */
	if ( usr <@ POP > anypath )	/* subscriber@pop */
		resolve (mailer (pop),
				host ($2),
				user ($1));

#ifdef ATHENA_MIT_EDU
	/* MX forwarding for uucp sites */
	if ( anypath <@ anypath "wgbh"."org"> anypath )
		resolve (mailer (uucp),
				host (wgbh),
				user ($1@$2 "wgbh" . "org" $3));
#endif

#ifdef BITNET_RELAY
	/* Bitnet mail goes to the bitnet relay $C using the TCP mailer */
	if ( zero_or_more <@ one_or_more ."BITNET"> zero_or_more )
		resolve (mailer (tcp),
				host ($C),
				user ($1<@$2."BITNET" >$3));
#endif

/* Hardcode routes to MITVMC & MITVMD for administrators. */
/* R$*<@MITVMC$*>$*	$1%MITVMC<@MITVMA.MIT.EDU>$3 */
	
	if ( zero_or_more <@"MITVMD" zero_or_more > zero_or_more )
		retry ($1%"MITVMD"<@"MITVMA"."MIT"."EDU">$3);

#ifdef CSNET_RELAY
	/* CSNET mail goes to the csnet relay $E using the TCP mailer */
	if ( zero_or_more <@ one_or_more ."CSNET"> zero_or_more )
		resolve (mailer (tcp),
				host ($E),
				user ($1<@$2>$3));
#endif

#ifdef MY_UUCP_NAME
	/* and UUCP mail goes thru the uucp mailer */
	if ( anypath <@ hostpath ."UUCP"> anypath )
		resolve (mailer (uucp),
				host ($2),
				user ($2!$1));
#else
#ifdef UUCP_RELAY
	/* and UUCP mail gets forwarded to the UUCP relay ($P) */
	if ( anypath <@ hostpath ."UUCP"> anypath )
		resolve (mailer (tcp),
				host ($P),
				user ($1<@$2."UUCP">$3));
#endif
#endif

#ifdef WATCH_COM
	/* all other foreign mail to the TCP mailer, posthaste */
	if ( zero_or_more <@ one_or_more > zero_or_more )
		resolve (mailer (tcp),
				host (TSX-11.MIT.EDU),
				user ($1<@$2>$3));
#else
	/* all other foreign mail to the TCP mailer, posthaste */
	if ( zero_or_more <@ one_or_more > zero_or_more )
		resolve (mailer (tcp),
				host ($2),
				user ($1<@$2>$3));
#endif

	/*
	 * It's dubious if we ever get here, since we should have
	 * rewritten the address in NAME_CANON to something with
	 * either @LOCAL or @MAILHUB in it.
	 */
#ifdef MAILHUB
#ifdef LOCALUSERS
	if ( localuser )		/* Local users here */
		resolve (mailer (local),
				user ($1));
	if ( localuser <> zero_or_more )
		resolve (mailer (local),
				user ($1));
#endif
	/* Send everything else to a mailhub */
	if ( usr )
		resolve (mailer (tcp),
				host ($M),
				user ($1));
#else
	/* anything else must be local */
	if ( usr )
		resolve (mailer (local),
				user ($1));
#endif
	}

