[comp.mail.sendmail] UK-2.1 part 1

idc@cs.hw.ac.uk (Ian Crorie) (01/20/89)

#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./README`
then
echo "Writing ./README"
cat > ./README << '\Rogue\Monster\'

		Sendmail Configuration Package UK-2.1
		======== ============= ======= ======

This package provides you with tools to generates a fully domain based
sendmail configuration file from domain and channel tables in a format
similar to that used by MMDF.

Documentation explaining how to use the package is in the Docs directory.

System V users should use the shellscript 'Support/SysV.sh' to convert
BSD specific commands to System V commands.

-Jim Crammond, Jem Taylor	December 1988

\Rogue\Monster\
else
  echo "Will not over-write ./README"
fi
chmod 444 ./README
if [ `wc -c < ./README` -ne 487 ]
then
echo 'Got' `wc -c < ./README` ', Expected ' 487
fi
if `test ! -s ./Config`
then
echo "Writing ./Config"
cat > ./Config << '\Rogue\Monster\'
#!/bin/sh
#
#  shell script to process a UK-sendmail configuration file and
#  generate a directory containing the relevent m4 files together
#  with a .mc file and Makefile which are used to build a sendmail.cf
#  
if [ $# -ne 1 ]
then
	echo usage: $0 file
	exit 1
elif [ ! -f $1 ]
then
	echo $1: file not found
	exit 1
fi

config=`echo $1 | sed 's/^config.//'`
configfile=$1
domfiles=
dombldargs=
chnfiles=
chnbldargs=

homedir=`pwd`
configdir=$config
tabledir=$config

#
#  transform the configuration file, then read in the resulting file
#
(cat $1; echo) | sed -n '
/#/s/#.*//
/^$/d
: repeat
N
s/\n[	 ][	 ]*//
t repeat
P
D
' > /tmp/config.$$

exec < /tmp/config.$$

#
#  process the configuration file
#
while read cmd arg1 arg2
do
	case $cmd in
	configdir=*|tabledir=*|install=*)
		val=`expr $cmd : '.*/'`
		if [ $val -gt 0 ]
		then
			echo $cmd: must be a subdirectory of this directory
		else
			eval $cmd
		fi
		;;
	config=*|domain=*|postmaster=*)
		eval $cmd
		var=`expr $cmd : '\(.*\)=.*' | tr '[a-z]' '[A-Z]'`
		eval val=$`expr $cmd : '\(.*\)=.*'`
		echo "define(\`$var',\`$val')dnl" >> /tmp/config.$$.mc
		;;
	options=*)
		eval $cmd
		opts=`echo $options | tr '[a-z]' '[A-Z]'`
		oldifs=$IFS ; IFS="," ; set $opts ; IFS=$oldifs

		for i in $*
		do
			echo "define(\`$i')dnl" >> /tmp/config.$$.mc
		done
		;;
	domain)
		if [ "$arg1" != "std" ]
		then
			dombldargs="$dombldargs-$arg1"
		fi

		eval $arg2
		domfiles="$domfiles $file "
		dombldargs="$dombldargs $file "
		;;
	channel)
		chn=`echo $arg1 | tr '[a-z]' '[A-Z]'`
		file=
		ldomain='$J'
		ida=

		oldifs=$IFS ; IFS="," ; set $arg2 ; IFS=$oldifs

		for i in $*
		do
			case $i in
			file=*|ldomain=*)
				eval $i
				;;
			ida)	ida="-ida "
				;;
			sysname=*|pgm=*)
				eval $i
				var=${chn}`expr $i : '\(.*\)=.*' | tr '[a-z]' '[A-Z]'`
				eval val=$`expr $i : '\(.*\)=.*'`
				echo "define(\`$var',\`$val')dnl" >> /tmp/config.$$.mc
				;;
			*)	opt=${chn}`echo $i | tr '[a-z]' '[A-Z]'`
				echo "define(\`$opt')dnl" >> /tmp/config.$$.mc
				;;
			esac
		done

		chnfiles="$chnfiles $file "
		chnbldargs="$chnbldargs$ida-$arg1 $file "

		if [ $arg1 != "top" ]
		then
			echo "define(\`${chn}NAME',\`$ldomain')dnl" >> /tmp/config.$$.mc
		fi
		;;
	esac

done

rm /tmp/config.$$

#
#  add a makefile for compiling tables in the tables directory
#
if [ ! -d $tabledir ]
then
	echo -n "
Making directory $tabledir ... "
	mkdir $tabledir
	if [ $? -ne 0 ]
	then	echo mkdir failed, aborted
		exit 1
	fi
fi

cd $tabledir
echo -n "
creating $tabledir/$config.mk ... "

cat > $config.mk <<EOF
############################################################
#
#	Makefile to compile sendmail tables for $config
#
############################################################

DOMFILES=$domfiles
DOMBLDARGS=$dombldargs

CHNFILES=$chnfiles
CHNBLDARGS=$chnbldargs

$config:	$config-dom.m4 $config-chn.m4

$config-dom.m4:	$(DOMFILES) $config.mk
		../Dombuild -o $config-dom.m4 $(DOMBLDARGS) 

$config-chn.m4:	$(CHNFILES) $config.mk
		../Chnbuild -o $config-chn.m4 $(CHNBLDARGS)

edit:
		\$\${VISUAL-vi} $(CHNFILES)
		\$\${VISUAL-vi} $(DOMFILES)

tidy:
		-rm -f [0-9]*.*

check:		$(CHNFILES) $(DOMFILES)
		../Chncheck $(CHNFILES)
		../Domcheck $(DOMFILES)
EOF

cd $homedir

#
#  create the sendmail configuration directory
#
if [ ! -d $configdir ]
then
	echo -n "
Making directory $configdir ... "
	mkdir $configdir
	if [ $? -ne 0 ]
	then	echo mkdir failed, aborted
		exit 1
	fi
fi

cd $configdir
echo -n "
creating configuration files in $configdir ... "

#
#  copy the relevent m4 files into the directory
#
ar x ../Rules.a

if [ -f localise.sh ]
then	echo -n "
running localise.sh in $configdir ... "
	./localise.sh
fi

#
#  create the Makefile
#
cat >Makefile <<EOF
########################################################################
#
#	Makefile for Sendmail configuration files
#
#	@(#)Makefile	UK-2.1 sendmail configuartion		18/11/88
#
########################################################################
RULES=base.m4 rules.m4 mailers.m4 version.m4

TBLDIR=../$tabledir
DOM_M4FILE=$config-dom.m4
CHN_M4FILE=$config-chn.m4

.SUFFIXES: .mc .cf

.mc.cf:
	-@mv \$*.cf \$*.cf.old
	m4 \$*.mc > \$*.cf

$config:	$(TBLDIR)/$config.mk
		cd $(TBLDIR); make -f $config.mk $config
		make $config.cf

$(TBLDIR)/$config.mk:	../$configfile
		( cd ..; Config $configfile )

$config.cf:	$(RULES) $(DOM_M4FILE) $(CHN_M4FILE) $(TBLDIR)/$config.mk

$(DOM_M4FILE):	$(TBLDIR)/$(DOM_M4FILE)
		cp $(TBLDIR)/$(DOM_M4FILE) .

$(CHN_M4FILE):	$(TBLDIR)/$(CHN_M4FILE)
		cp $(TBLDIR)/$(CHN_M4FILE) .

install:
		sh ../Install.sh $install $config

test:
		/usr/lib/sendmail -bt -C$config.cf

edit check tidy: $(TBLDIR)/$config.mk
		cd $(TBLDIR); make -f $config.mk \$@

diff:		$config.cf $config.cf.old
		wc $config.cf.old $config.cf
		diff $config.cf.old $config.cf
EOF

#
#  create the config.mc file
#
mv /tmp/config.$$.mc $config.mc
cat >> $config.mc <<EOF
include(base.m4)
include(rules.m4)
include($config-dom.m4)
include($config-chn.m4)
include(mailers.m4)
EOF

echo
exit
\Rogue\Monster\
else
  echo "Will not over-write ./Config"
fi
chmod 555 ./Config
if [ `wc -c < ./Config` -ne 5014 ]
then
echo 'Got' `wc -c < ./Config` ', Expected ' 5014
fi
if `test ! -s ./Dombuild`
then
echo "Writing ./Dombuild"
cat > ./Dombuild << '\Rogue\Monster\'
#!/bin/sh
#
#  shell script to generate a sendmail dom-tbl.m4 file containing all
#  the domain information for this site from a set of domain tables.
#

if [ $# -le 1 ]
then	echo	usage: $0 [-ida file] files ... -top file
	exit
fi

rm -f $$.*
outf=dom-tbl.m4
strip="sed -e /#/s/#.*// -e /^\$/d"
classes="ABCEFGHIKLM"
cp /dev/null $$.S10

ida=
top=
rest=

while [ $# -gt 0 ]
do
	case $1 in
	-o)		outf=$2
			shift
			;;
	-ida)		ida="$ida $2"
			shift
			;;
	-top)		top="$top $2"
			shift
			;;
	*)		rest="$rest $1"
			;;
	esac
	shift
done

if [ -n "$ida" ]
then
	set $ida
	dbmfile=`basename $1 .dom`

	$strip $ida | awk '
NF==1	{ $2 = $1; $1 = substr($2, 1, index($2,".")-1) }	# shorthand
	{ print $1 "	" $2 }
	' |  dbm load - $dbmfile

	echo "OKA`pwd`/$dbmfile" > $$.S10
	echo 'R$+@$+		$:$1@$(A $2 $)		lookup db' >> $$.S10
fi

$strip $top | awk '{ printf "%s %s.TOP_LEVEL_DOM\n",$1,$1 }' > $$.top

$strip $$.top $rest | awk '
NR==1	{ MINCLSIZE = 3
	  c = 1
	  S10 = prefix "S10"
	  S11 = prefix "S11"
	  S12 = prefix "S12"
	  S13 = prefix "S13"
	  cl_outd = prefix "classf"
	}
NF==1	{ $2 = $1	# shorthand
	  $1 = substr($2, 1, index($2,".")-1)
	}
	{ i = index($2,".")
	  lpart = substr($2,1,i-1)

	  if ($1 != lpart)
	  	printf "R$*%s\t\t$1%s\n", $1, $2	>> S10
	  else
	  {	rpart = substr($2,i+1)
		domain[rpart] = domain[rpart] " " lpart
		n = split(rpart, doms, ".")
		rparts[rpart] = n
	  }
	}

END	{
	    for (i in rparts)
	    {	order[rparts[i]] = order[rparts[i]] " " i
		if (rparts[i] > maxn)
			maxn = rparts[i]
	    }

	    for (i=1; i <= maxn; i++)
	    {	m = split(order[i], rpts, " ")
		for (j=1; j<=m; j++)
		{   rhs = rpts[j]
	    	    d = split(domain[rhs], subdoms, " ")

		    if (rhs == "TOP_LEVEL_DOM")
			printf "\nCT%s\n", domain[rhs]		>cl_outd
		    else if (d >= MINCLSIZE && c <= length(classes))
		    {	C = substr(classes, c, 1)
			c++
			printf "\nD%s%s\n", C, rhs		>cl_outd
			printf "C%s%s\n", C, domain[rhs]	>cl_outd
			printf "R$*$=%s\t\t\t$@$1$2.$%s\t\tu@d -> u@d.%s\n", \
					C, C, rhs >S11
			printf "R$*$=%s.$%s\t\t$@$1$2\t\tu@d.%s -> u@d\n", \
					C, C, rhs >S12
			printf "R$*$=%s\t\t\t$@$1$2\n", C	>S13
			printf "R$*@$=%s.$+\t\t$@$>9$1@$2.$3\n", C >S13
		    }
		    else
		    {	for (k=1; k<=d; k++)
			{	printf "R$*%s\t\t$@$1%s.%s\n", subdoms[k], \
					subdoms[k], rhs  >S11
				printf "R$*%s.%s\t\t$@$1%s\n", subdoms[k], \
					rhs, subdoms[k]  >S12
				printf "R$*%s\t\t\t$@$1%s\n", \
					subdoms[k], subdoms[k]  >S13
				printf "R$*@%s.$+\t\t$@$>9$1@%s.$2\n", \
					subdoms[k], subdoms[k]  >S13
			}
		    }
		}
	    }
	}
' prefix=$$. classes=$classes -

#
#  The header
#
cat > $outf <<EOF
###############################################################################
#####
#####	@(#)$outf	UK-2.1 sendmail configuration		18/11/88
#####
#####	The domain database and rules
#####
###############################################################################

# classes
EOF

#
#  generate classes
#
while read class group
do
	echo $group | tr ' ' '\012' | fmt | sed "s/^/$class/"
done  < $$.classf >> $outf


#
#  Ruleset 10
#
cat - $$.S10 >> $outf <<'EOF'

##########################################
#  Ruleset 10  --  domain name aliasing  #
##########################################

S10
EOF

#
#  Ruleset 11
#
cat - $$.S11 >> $outf <<'EOF'

########################################################
#  Ruleset 11  --  Expand address to full domain name  #
########################################################

S11
R$*$=T			$@$1$2		already fully qualified
EOF

#
#  Ruleset 12
#
cat >> $outf <<'EOF'

ifdef(`LOCALSHOWUUCP',`
############################################################
#  Ruleset 12  --  Strip full domain name to minimum part  #
############################################################

S12
EOF
( tail -r $$.S12 ; echo "')" ) >> $outf

#
#  Ruleset 13
#
cat - $$.S13 >> $outf <<'EOF'

ifdef(`NRSFORMAT',`
###############################################################
#  Ruleset 13  --  Convert domains in NRS order to 822 order  #
###############################################################

S13
R$*$=T			$@$1$2
R$*@$=T.$+		$@$>9$1@$2.$3
EOF
echo "')" >> $outf

rm -f $$.*
exit
\Rogue\Monster\
else
  echo "Will not over-write ./Dombuild"
fi
chmod 555 ./Dombuild
if [ `wc -c < ./Dombuild` -ne 4163 ]
then
echo 'Got' `wc -c < ./Dombuild` ', Expected ' 4163
fi
if `test ! -s ./Chnbuild`
then
echo "Writing ./Chnbuild"
cat > ./Chnbuild << '\Rogue\Monster\'
#!/bin/sh
#
#  shell script to generate a sendmail chn-tbl.m4 file containing all
#  the routing information for this host from a set of channel tables.
#
if [ $# -le 1 ]
then	echo	"usage: $0 [-o outfile] -chn file..."
	exit
fi

#
#  first, create the awk programs that compile the channel tables
#

rm -f $$.*
outf=chn-tbl.m4

#
#  Standard format channel compiler
#
cat > $$.std.awk <<'EOF'
NR==1	{
	MINCLSIZE = 3
	c = 1
	mailer = substr(mailer, 2)
	cl_outl = prefix "classl"
	cl_outf = prefix "classf"
	printf "\n# %s (%s channel)\n", file, mailer
	}

NF==1	{ $2 = substr($1, 1, index($1,".")-1) }		# shorthand

/%s/	{
	# process wildcards
	lhs = sprintf($1,"$+","$+","$+")
	rhs = sprintf($1,"$2","$3","$4")
	dest = sprintf($2,"$2","$3","$4")
	printf "R$+@%s\t\t$@<$1@%s>%s.%s\n", lhs, rhs, dest, mailer >> S16
	break
	}

	{
	i = index($1, ".")
	subdom = substr($1,1,i-1)
	restdom = substr($1,i+1)

	if (subdom == $2 && restdom != "")
		link["$2/" restdom] = link["$2/" restdom] " " subdom
	else
		link[ $2 "/" restdom ] = link[ $2 "/" restdom ] " " subdom
	}

END	{
	for (i in link)
	{	j = index(i,"/")
		dest = substr(i, 1, j-1)
		rdom = substr(i, j+1)
		n = split(link[i], sub, " ")
		if (n >= MINCLSIZE && c <= length(classes))
		{	C = substr(classes, c, 1)
			c++
			printf "C%s%s\n", C , link[i]	>> cl_outf
			printf "R$+@$=%s.%s\t\t$@<$1@$2.%s>%s.%s\n", \
				C, rdom, rdom, dest, mailer
		}
		else
		{	host = dest
			for (j=1; j<=n; j++)
			{	if (dest == "$2") host = sub[j]
				printf "R$+@%s.%s\t\t$@<$1@%s.%s>%s.%s\n", \
					sub[j], rdom, sub[j], rdom, host, mailer
			}
		}
	}

	print "" >>cl_outf
	print substr(classes, c) > cl_outl
	}
EOF

#
#   Janet channel compiler
#
cat > $$.janet.awk <<'EOF'
NR==1	{
	printf "\n# %s (Janet channel)\n", file
	swap1 = sprintf("R$+@$+\t\t$:$>9$1@$2\t\tconvert to NRS style")
	swap2 = sprintf("R$+@$+\t\t$:$>9$1@$2\t\tconvert back to 822 style")
	}

NF==1	{ $2 = $1 }		# shorthand

/%s/	{
	if (wcnt++ == 0)  print swap1 >> S16

	# process wildcards
	lhs = sprintf($1,"$+","$+","$+")
	rhs = sprintf($1,"$2","$3","$4")
	dest = sprintf($2,"$2","$3","$4")
	if (rhs == dest)
		jntaddr = "$1@" dest
	else
		jntaddr = "$1%" rhs "@" dest
	printf "R$+@%s\t\t$@<%s>%s.janet\n", lhs, jntaddr, dest >> S16
	break
	}

	{
	if (cnt++ == 0)  print swap1

	if ($1 == $2)
		jntaddr = "$1@" $2
	else
		jntaddr = "$1%" $1 "@" $2
	printf "R$+@%s\t\t$@<%s>%s.janet\n", $1, jntaddr, $2
	}

END	{
	if (cnt > 0) print swap2
	if (wcnt > 0) print swap2 >> S16
	}
EOF

#
#  UUCP channel compiler
#
cat > $$.uucp.awk <<'EOF'
NR==1	{
	MINCLSIZE = 3
	c = 1
	link[""]=""
	cl_outl = prefix "classl"
	cl_outf = prefix "classf"
	printf "\n# %s (UUCP channel)\n", file
	printf "R$+@$+\t\t\t$:$>8$1@$2\t\tconvert to uucp addresses\n"
	}

	{
	i = index($1, ".")
	subdom = substr($1,1,i-1)
	restdom = substr($1,i+1)
	udest = subdom "!%s"

	if (NF == 1) $2 = udest		# shorthand

	if (udest == $2)
		link[ "/" restdom ] = link[ "/" restdom ] " " subdom
	else
	{	pathl = length($2) - length(udest)
		if ( substr($2, pathl) == ("!" udest) )
		{	path = substr($2, 1, pathl-1)
			link[ path "/" restdom ] = link[ path "/" restdom ] " " subdom
		}
		else
		{	i = index($2, "!")
			host = substr($2,1,i-1)
			addr = sprintf( substr($2,i+1), "$1")
			printf "R%s!$+\t\t$@<%s>%s.uucp\n", $1, addr, host
		}
	}
	}

END	{
	for (i in link)
	{	j = index(i, "/")
		path = substr(i, 1, j-1)
		rdom = substr(i, j+1)
		p = index(path, "!")
		n = split(link[i], sub, " ")
		if (n >= MINCLSIZE && c <= length(classes))
		{	C = substr(classes, c, 1)
			c++
			printf "C%s%s\n", C, link[i]	>>cl_outf
			if (path == "")
			{	host = "$1"
				addr = ""
			}
			else if (p == 0)
			{	host = path
				addr = "$1!"
			}
			else
			{	host = substr(path,1,p-1)
				addr = substr(path,p+1) "!$1!"
			}
			printf "R$=%s.%s!$+\t\t$@<%s$2>%s.uucp\n", C, rdom, addr, host
		}
		else
		{	for (j=1; j<=n; j++)
			{	if (path == "")
				{	host = sub[j]
					addr = ""
				}
				else if (p == 0)
				{	host = path
					addr = sub[j] "!"
				}
				else
				{	host = substr(path,1,p-1)
					addr = substr(path,p+1) "!" sub[j] "!"
				}
				printf "R%s.%s!$+\t\t$@<%s$1>%s.uucp\n", \
						sub[j], rdom, addr, host
			}
		}
	}
	print "" >>cl_outf
	print substr(classes, c) > cl_outl
	print "\nR$+!$+\t\t\t$:$>7$1!$2\t\tconvert back to 822 style\n"
	}
EOF

#
#  News channel compiler
#
cat > $$.news.awk << 'EOF'
NR==1	{ printf "\n# %s (news channel)\n", file }
	{
	lhs = sprintf($1,"$+","$+","$+")
	rhs = sprintf($1,"$1","$2","$3")
	dest = sprintf($2,"$1","$2","$3")

	if (NF == 1)
		printf "R%s\t\t$@<%s>news\n", lhs, rhs
	else
		printf "R%s\t\t$@$>3 %s@%s\n", lhs, rhs, dest
	}
EOF


#
#  Top level domain relay compiler
#
cat > $$.top.awk <<'EOF'
NR==1	{
	MINCLSIZE = 3
	c = 1
	cl_outl = prefix "classl"
	cl_outf = prefix "classf"
	relay[""] = ""
	}
$1=="DEFAULT" || $1=="$=T"	{ default = $2 ; break }
$1=="ALL" || $1=="$+"		{ all = $2 ; break }

	{ relay[$2] = relay[$2] " " $1 }

END	{
	for (i in relay)
	{	n = split(relay[i], doms, " ")
		if (n >= MINCLSIZE && c <= length(classes))
		{	C = substr(classes, c, 1)
			c++
			printf "C%s%s\n", C, relay[i]	>> cl_outf
			printf "R$+@$+.$=%s\t\t$@$>16$1%%$2.$3@%s\n", C, i
		}
		else
		{	for (j=1; j<=n; j++)
				printf "R$+@$+.%s\t\t$@$>16$1%%$2.%s@%s\n", \
					doms[j], doms[j], i
		}
	}
	if (default)	printf "R$+@$+.$=T\t\t$@$>16$1%%$2.$3@%s\n", default
	if (all)	printf "R$+@$+\t\t$@$>16$1%%$2@%s\n", all

	print "" >>cl_outf
	print substr(classes, c) > cl_outl
	}
EOF

#---------------------------------------

#
#  awk scripts for compiling to ida databases
#
cat > $$.std.ida.awk <<'EOF'
NR==1	{
	mailer = substr(mailer, 2)
	printf "\n# %s (%s channel)\n", file, mailer
	printf "R$+@$+\t\t$:$(%s $2 $@ $1 $: $1@$2 $)\t\tlookup database\n",key
	printf "R<$+>$+.%s\t\t$@<$1>$2.%s\t\tfound a match\n", mailer,mailer
	}
NF==1	{ $2 = substr($1, 1, index($1,".")-1) }		# shorthand
	{ printf "%s\t<%%s@%s>%s.%s\n", $1, $1, $2, mailer > dbmf }
EOF

cat > $$.janet.ida.awk <<'EOF'
NR==1   {
	printf "\n# %s (Janet channel)\n", file
	printf "R$+@$+\t\t$:$>9$1@$2\t\tconvert to NRS style\n"
	printf "R$+@$+\t\t$:$(%s $2 $@ $1 $: $1@$2 $)\t\tlookup database\n",key
	printf "R<$+>$+.janet\t\t$@<$1>$2.janet\t\tfound a match\n"
	}
NF==1	{ $2 = $1 }		# shorthand
	{
	if ($1 == $2)
		jntaddr = "%s@" $2
	else
		jntaddr = "%s%%" $1 "@" $2

	printf "%s\t<%s>%s.janet\n", $1, jntaddr, $2 > dbmf
	}
END     { printf "\nR$+@$+\t\t$:$>9$1@$2\t\tconvert back to 822 style\n" }
EOF


#---------------------------------------

#
#  compile the tables; output goes into various files
#

strip="sed -e /#/s/#.*// -e /^\$/d"
classes="NOPQRSUVWXYZ"
dbkeys="BCDEFHIJ"
cp /dev/null $$.classf

while [ $# -gt 0 ]
do
	case $1 in

	-o)	outf=$2
		;;

	-local)	$strip -e 's/^LHOST\./$=w./' $2 | awk '
		{ printf "R$+@%s\t\t$@$1@$J\n", $1	   >> S15
		  printf "R$+@%s\t\t$@<$1@$J>error\n", $1  >> S17
		}'  S15=$$.S15  S17=$$.S17 -
		;;

	-ether|-tcp|-csnet|-decnet|-xerox)
		$strip $2 | awk -f $$.std.awk mailer=$1 file=$2 prefix=$$. \
			    classes=$classes S16=$$.S16 - >> $$.S17
		classes=`cat $$.classl`
		;;

	-janet)	$strip $2 | awk -f $$.janet.awk file=$2 S16=$$.S16 - >> $$.S17
		;;

	-uucp)	$strip $2 | awk -f $$.uucp.awk file=$2 prefix=$$. \
			    classes=$classes - >> $$.S17
		classes=`cat $$.classl`
		;;

	-news)	$strip $2 | awk -f $$.news.awk file=$2 - >> $$.S18
		;;

	-top)	$strip $2 | awk -f $$.top.awk prefix=$$. \
			    classes=$classes - >> $$.S16
		classes=`cat $$.classl`
		;;

	-ida)	shift
		key=`expr substr $dbkeys 1 1`
		dbkeys=`expr substr $dbkeys 2 26`
		dbmfile=`basename $2 .chn`

		case $1 in
		-janet)	$strip $2 | awk -f $$.janet.ida.awk file=$2 \
				key=$key dbmf=$dbmfile.ida - >> $$.S17
			;;

		*)	$strip $2 | awk -f $$.std.ida.awk mailer=$1 file=$2 \
				key=$key dbmf=$dbmfile.ida - >> $$.S17
			;;
		esac

		dbm load $dbmfile.ida $dbmfile
		echo "OK$key`pwd`/$dbmfile" >> $$.S17
		rm $dbmfile.ida
		;;

	*)	echo "usage: $0 [-o file] -chn file..."
		rm -f $$.*
		exit 1
		;;
	esac
	shift 2
done

#---------------------------------------

#
#  now glue all the bits together
#

#
#  The header
#
cat > $outf <<EOF
###############################################################################
#####
#####	@(#)$outf	UK-2.1 sendmail configuration		18/11/88
#####
#####	The mailer selection and routing
#####
###############################################################################

# classes
EOF

#
#  the classes
#
while read class group
do
	echo "$group" | fmt | sed "s/^/$class/"
done < $$.classf >> $outf

#
#  the rules
#
cat - $$.S15 >> $outf <<'EOF'

###########################################
#  Ruleset 15  --  local domain handling  #
###########################################

#
#  This rule converts various forms of local domain names
#  into the standard ($J) name
#

S15
ifdef(`MULTIHOST',
`R$+@$=w.$J		$@$1@$J			host specific name')
EOF

cat - $$.S16 >> $outf <<'EOF'

#############################
#  Ruleset 16  --  routing  #
#############################

#
#  This rule trys to find an "<address>host.network" triple for a given
#  domain address.  Given a domain address "u@a.b.c.d", it calls the
#  channel matcher with u@a.b.c.d, and if nothing matched, it calls
#  the channel matcher again, with "u%a.b.c.d@b.c.d" and  "u%a.b.c.d@c.d".
#  If there's still no match, then the top level domain relaying is done
#  e.g. "u%a.b.c.d@d" -> "u%a.b.c.d@x.y.z" and the rule is retried.
#

S16
R$+@$+			$:$>17$1@$2		initial routing
R<$+>$+			$@<$1>$2		success, return triple

#  initial match failed, retry with successively higher level domains
R<$+@$+>		$:<$1%$2@$2>		u@a.b.c -> u%a.b.c@a.b.c
R<$+@$-.$+>		$>17$1@$3		retry routing
R<$+>$+			$@<$1>$2		success, return triple

#  match failed, attempt to match with "general" rules (wildcards);
#  if this fails then try matching top level domain to find relay domain
R<$+@$->		$:$>4$1			restore original address

EOF

cat - $$.S17 >> $outf <<'EOF'

######################################
#  Ruleset 17  --  channel matching  #
######################################

#
#  This rule takes a full domain address and trys to match it with a
#  domain given on the LHS of a rule.
#  If one matches, the "<address>host.network" triple given on the RHS
#  is returned.  Else  "<address>" is returned.
#

S17
R$+@$J			$@<$1@$J>error		unknown local subdomain error
EOF

#
#  complete ruleset 17
#
cat >> $outf <<'EOF'

R$+			$@<$1>			no match, return "<address>"
EOF

if [ -f $$.S18 ]
then	cat - $$.S18 >> $outf <<'EOF'

#############################################
#  Ruleset 18  --  newsgroup name matching  #
#############################################

#
#  This rule takes a local address and trys to match it with a
#  newsgroup name given on the LHS of a rule.
#  If one matches, the "<name>news" double given on the RHS
#  is returned. If a relayed newsgroup is found, ruleset 3 is
#  re-entered with name@relay. Else  "address" is returned.
#

S18
# send non-local addresses straight back
R$+@$+          	$@$1@$2         	not a local address

EOF
fi

rm -f $$.*
exit
\Rogue\Monster\
else
  echo "Will not over-write ./Chnbuild"
fi
chmod 555 ./Chnbuild
if [ `wc -c < ./Chnbuild` -ne 11085 ]
then
echo 'Got' `wc -c < ./Chnbuild` ', Expected ' 11085
fi
if `test ! -s ./Rules.a`
then
echo "Writing ./Rules.a"
cat > ./Rules.a << '\Rogue\Monster\'
!<arch>
base.m4         600449291   548   22    100444  3075      `
##################################################################
##################################################################
#####
#####		SENDMAIL CONFIGURATION FILE  UK-2.1
#####
##### Copyright (C) November 1988, Jim Crammond, Imperial College
#####				   Jem Taylor, Glasgow University
#####
#####	This configuration file maybe be freely distributed,
#####	provided that this notice and copyright is preserved.
#####	This software is provided as is without any warranty.
#####
##################################################################
##################################################################

##################################################################
`###'	CONFIG configuration file
##################################################################

# offical site domain name
DJ`'DOMAIN

# offical host domain name
ifdef(`MULTIHOST',`Dj$w.$J',`Dj$J')

# uucp hostname
ifdef(`UUCPNAME',DU`'UUCPSYSNAME)

############################################################
#
#	General configuration information
#
############################################################

DVUK-2.1
ifdef(`HISTORY',`include(version.m4)')

##########################
###   Special macros   ###
##########################

# my name
Dn`'POSTMASTER
# UNIX header format
DlFrom $g $d remote from $U
# delimiter (operator) characters (note '~' has been added)
Do.:%@!^=/[]~
# format of a total name
Dq$?x$x <$g>$|$g$.
# SMTP login message
De$j Sendmail $v/$V ready at $b

###################
###   Options   ###
###################

# location of alias file
OA/usr/lib/aliases
# default delivery mode (deliver in background)
Odbackground
# mail to me too (needed for multihost sites)
Om
# (don't) connect to "expensive" mailers
#Oc
# automatically do newaliases when aliases.dbm out of date
#OD
# temporary file mode 
OF0644
# default GID
Og1
# location of help file
OH/usr/lib/sendmail.hf
# log level
OL9
# default messages to old style
Oo
# Cc my postmaster on error replies I generate
#OP`'POSTMASTER
# queue directory
OQ/usr/spool/mqueue
# read timeout -- violates protocols
Or2h
# status file
OS/usr/lib/sendmail.st
# queue up everything before starting transmission
# Os
# default timeout interval
OT3d
# time zone names (V6 only)
# OtGMT,BST
# default UID
Ou1
# wizard's password
OWz3GvK.dPUxieQ
# load averages at which to start queuing/refuse connections
Ox8
OX12
# penalty per recipient
#Oy1000
# memory-poor environmenet
#OY
# boost for high-priority messages
#Oz1800
# penalty for being retried
#OZ0

###############################
###   Message precedences   ###
###############################

Pfirst-class=0
Pspecial-delivery=100
Pjunk=-100

#########################
###   Trusted users   ###
#########################

Troot
Tdaemon
Tuucp
Tmail

#############################
###   Format of headers   ###
#############################

H?F?From: $q
H?D?Date: $a
H?M?Message-Id: <$p.$t@$j>
H?F?Resent-From: $q
H?D?Resent-Date: $b
H?M?Resent-Message-Id: <$p.$t@$j>
HSubject:
HReceived: $?sfrom $s by $j; $b$.
HVia: $?S$S; $b$.
undefine(`unix')

rules.m4        595853294   548   22    100444  6941      `
###############################################################################
###############################################################################
#####
#####	@(#)rules.m4	UK-2.1 sendmail configuration		18/11/88
#####
#####		The rulesets
#####
###############################################################################
###############################################################################

###############################################
#  Ruleset 0  --  Select mailer to be used    #
###############################################
S0

# strip local domain name(s)
R$+@$J			$>3$1			process local part

ifdef(`NEWSNAME',
`#  compare local-part with newsgroup names 
R$+			$:$>18$1		newsgroups in local-part')

# local mail
R$-			$#local$:<$1>		local mail - maybe aliased
R~$-			$#binmail$:<$1>		local mail - no aliasing

#
# convert domain address into "<address>host.network" triple
#
R$+@$+			$:$>16$1@$2		routing and address conversion

#
# select mailer
#

# note that address part ($u) is returned as "<address>"; the brackets are
# subsequently removed in ruleset 4 (or 3 in the case of the smtp channel).
# Such addresses can then be ignored by the header rulesets which are called
# in BSD4.3 based sendmail.

ifdef(`ETHERNAME',
`R<$+>$+.ether		$#ether$@$2$:<$1>	local ethernet mail')
ifdef(`TCPNAME',
`R<$+>$+.tcp		$#tcp@$2$:<$1>		internet mail
R$+@[$+]		$#tcp$@[$2]$:<$1>	pass domain literals to tcp')
ifdef(`UUCPNAME',
`R<~$+>$+.uucp		<\\~$1>$2.uucp		band-aid for uuxqt
R<$+>$+.uucp		$#uucp$@$2$:<$1>	external uucp mail')
ifdef(`JANETNAME',
`R<$+>$+.janet		$#niftp$@$2$:<$1>	janet mail')
ifdef(`NEWSNAME',
`ifdef(`NEWSRELAYED',`',
`R<$+>news		$#news$:<$1>		network news')')
ifdef(`CSNETNAME',
`R<$+>$+.csnet		$#pmdf$@$2$:<$1>	csnet mail')
ifdef(`DECNETNAME',
`R<$+@$+>$+.decnet	$#mail11$@$3$:<$1>	decnet mail')
ifdef(`XEROXNAME',
`R<$+>$+.xerox		$#xerox$@$2$:<$1>	xerox mail')

R<$+>error		$#error$:Local Domain Unknown
R<$+>$+			$#error$:Configuration Error

# anything else with an "@" in is an error
R$+@$+			$#error$:Domain Unknown

# anything else - e.g. filenames, pipes etc goes to local mailer
R$+			$#local$:<$1>		local


###############################################
#  Ruleset 1  --  Sender Field Pre-rewriting  #
###############################################
S1
R$+@$J			$@$1			strip local domain name


##################################################
#  Ruleset 2  --  Recipient Field Pre-rewriting  #
##################################################
S2
R$+@$J			$@$1			strip local domain name


##########################################
#  Ruleset 3  --  Name Canonicalisation  #
##########################################
S3

#  handle special cases
R$-			$@$1			return "user"
R~$-			$@~$1			return "~ user"

#  basic textual canonicalisation
R$*<$*>$*		$2			basic RFC 822 parsing
R$+\ at\ $+		$1@$2			" at " -> "@" for RFC 822
R$+%$+			$1@$2			convert '%'s to '@'s
R$+@$+@$+		$1%$2@$3		then reduce to only one '@'

#  Address conversions.
R@$+:$+			$:$>5@$1:$2		RFC822 to Percent form
R$+::$+			$1!$2			decnet to uucp form
R$+!$+			$:$>7$1!$2		uucp to Percent form
ifdef(`NRSFORMAT',
`R$+@$+.$+		$:$>13$1@$2.$3		NRS ordering to 822 ordering')

#  Domain name expansion.
ifdef(`NAMESERVER',
`R$+@$+			$:$1@$[$2$]		canonical name from nameserver')
R$+@$+			$:$>11$1@$2		expand incomplete domain names
R$+@$+			$:$>10$1@$2		do domain name aliases

R$+@$+			$:$>15$1@$2		standardise local domain name

###############################################
#  Ruleset 4  --  Final Output Post-rewriting #
###############################################

#  header rewriting is done in the per-mailer rulesets.

S4
R<$+>			$:$1			remove brackets from $u addr
R$+@$+			$@$1@$2			already ok

#  this ensures that $u has at least one '@' in (if percent style)
R$+%$+			$1@$2			convert '%'s to '@'s
R$+@$+@$+		$1%$2@$3		then reduce to only one '@'


########################################################
#  Ruleset 5  --  RFC source routing -> Percent style  #
########################################################

#
#  convert a routed address in RFC822 form to Percent form
#  e.g. @ucl-cs.arpa,@kcl-cs.uucp:jim@hwcs.uucp  ->
#					jim%hwcs.uucp%kcl-cs.uucp@ucl-cs.arpa
#
S5

R$+,$+			$1:$2			@a,@b,@c:u%d -> @a:@b:@c:u%d
R$*@$*			$1%$2			@a:@b:@c:u@d -> %a:%b:%c:u%d

R%$+:$+			$:$2@$1			%a:%b:%c:u%d -> %b:%c:u%d@a
R%$+:$+@$+		$2@$1@$3		%b:%c:u%d@a  -> u%d@c@b@a
R$+@$+@$+		$1%$2@$3		u%d@c@b@a    -> u%d%c%b@a

ifdef(`TCPNAME',`
##############################################################
#  Ruleset 6  --  Percent style source routing -> RFC style  #
##############################################################

#
#  convert a routed address in the Percent form to RFC822 form
#  e.g.	jim%hwcs.uucp%kcl-cs.uucp@ucl-cs.arpa  ->
#				@ucl-cs.arpa,@kcl-cs.uucp:jim@hwcs.uucp
#	BEWARE!
#	This ruleset is only safe to use for transport addr in SMTP headers
#	because we cannot determine whether to add brackets and a phrase
#
S6

R$+@$+			$1%$2			u%d%c%b@a    -> u%d%c%b%a
R$+%$+%$+		$:@$3:$1@$2		u%d%c%b%a    -> @c%b%a:u@d
R$+%$+:$+		@$2:$1:$3		@c%b%a:u%d   -> @a:@b:@c:u@d
R$+:$+:$+		$1,$2:$3		@a:@b:@c:u@d -> @a,@b,@c:u@d
')

###############################################################
#  Ruleset 7  --  uucp style source routing -> Percent style  #
###############################################################

#
#  convert an address in uucp form to Percent form
#  e.g. kcl-cs.uucp!hwcs.uucp!jim -> jim%hwcs.uucp@kcl-cs.uucp
#
#  also converts mixed addresses, giving '@' and '%' priority over '!'
#  e.g. hwcs!jim%kcl-cs.uucp@ucl-cs.arpa -> jim%hwcs%kcl-cs.uucp@ucl-cs.arpa
#
S7

# handle mixed addresses (with '!'s, '@'s and maybe '%'s in)
R$+!$+%$+		$1!$2@$3		c!d!u%b@a -> c!d!u@b@a
R$+!$+@$+		$2@$1@$3		c!d!u@b@a -> u@d@c@b@a

# handle pure uucp addresses
R$+!$+			$:$2@$1			a!b!c!d!u -> b!c!d!u@a
R$+!$+@$+		$2@$1@$3		b!c!d!u@a -> u@d@c@b@a

R$+@$+@$+		$1%$2@$3		u@d@c@b@a -> u%d%c%b@a

###############################################################
#  Ruleset 8  --  Percent style to uucp style source routing  #
###############################################################

#
#  convert a Percent style address to uucp (domain1!domain2!user) form
#  e.g. jim%hwcs.uucp@kcl-cs.uucp -> kcl-cs.uucp!hwcs.uucp!jim
#
S8

R$+%$+			$1@$2			u%d%c%b@a -> u@d@c@b@a
R$+@$+			$:$2!$1			u@d@c@b@a -> d@c@b@a!u
R$+@$+!$+		$2!$1!$3		d@c@b@a!u -> a!b!c!d!u

ifdef(`NRSFORMAT',`
#####################################################
#  Ruleset 9  --  NRS <-> RFC822 domain conversion  #
#####################################################

#
# swap the order of the sub-domains around.
# e.g. steve@uk.ac.ucl-cs.44d => steve@44d.ucl-cs.ac.uk
#
# this assumes that no colons will appear in the rhs of the domain address
#
S9

R$*@$+.$+		$1@$2:$3		u@a.b.c.d -> u@a:b:c:d
R$*@$-:$+		$:$1@$3.$2		u@a:b:c:d -> u@b:c:d.a
R$*@$-:$+.$+		$1@$3.$2.$4		u@b:c:d.a -> u@d.c.b.a
')

mailers.m4      595853944   548   22    100444  6204      `
###############################################################################
###############################################################################
#####
#####	@(#)mailers.m4	UK-2.1 sendmail configuration		18/11/88
#####
#####		The Mailer specifications
#####
###############################################################################
###############################################################################


####################################################################
###
###		Local and Program Mailer specification
###
####################################################################

Mlocal,   P=/bin/mail, F=rnlsmFD, S=20, R=20, A=mail -d $u 
Mbinmail, P=/bin/mail, F=rnlsmFD, S=20, R=20, A=mail -d $u 
Mprog,    P=/bin/sh,   F=nlsFD,   S=20, R=20, A=sh -c $u 

S20
R<$+>			$@<$1>			return transport addr

R~$+			$1			remove '~' in To: line
R$+@[$+]		$@$1@[$2]		domain literals

ifdef(`LOCALSHOWUUCP',
`# we assume an address is a uucp address if it contains more than two
# hostnames (as opposed to domain names). This is not always right..
R$+%$-%$-@$+		$:$>12$1%$2%$3@$4	strip outer domain name
R$+%$-%$-@$+		$@$>8$1%$2%$3@$4	convert to uucp address')

ifdef(`LOCALSHOWNRS',
`R$+@$-.$+		$@$>9$1@$2.$3		convert to NRS ordering')

ifdef(`LOCALSHOWLDOMAIN',
`R$+@$+			$@$1@$2			return non-local address
ifdef(`LOCALSHOWNRS',
`R$+			$@$>9$1@$J		add local domain - NRS style',
`R$+			$@$1@$J			add local domain - 822 style')')

ifdef(`ETHERNAME',`
###################################################################
###
###		Ethernet Mailer specification
###
###################################################################

Mether,	P=[IPC], F=nsmFDMuXC, S=21, R=21, A=IPC $h

S21
R$+@$+			$@$1@$2			address ok
R$+			$@$1@ETHERNAME		add ether domain name')

ifdef(`TCPNAME',`
###################################################################
###
###		TCP Mailer specification
###
###################################################################

Mtcp,	P=[IPC], F=nsmFDMuXL, S=22, R=22, A=IPC $h, E=\r\n 

#
#  header addresses are kept in percent style, rather than 822 style as
#  sendmail can not produce a correct routed 822 address from another style
#
S22
R<$+>			$@$>6$1			transport addr in 822 style

R$+@$+			$@$1@$2			address ok
R$+			$@$1@TCPNAME		add tcp domain name')

ifdef(`UUCPNAME',`
###################################################################
###
###		UUCP Mailer specification
###
###################################################################

ifdef(`UUCPMUUCP',`
Muucp, F=nsmFDMuh, S=23, R=23, M=100000, ifdef(`UUCPAUTH',`
	P=/usr/lib/authorise, A=authorise uucp $g $h /usr/lib/uucp/',`
	P=/usr/lib/uucp/muucp, A=')muucp -r -gA -f$f@UUCPNAME -H$U $h $u

#
#  RFC 976 style.  Note, however, that addresses are kept in percent style,
#  rather than 822 style as sendmail can not produce a correct routed 822
#  address from another style
#
S23
R<$+>			$@<$1>			return transport addr

R$+@$+			$@$1@$2			address ok
R$+			$@$1@UUCPNAME		add uucp domain name',`
Muucp, F=sFDMuh, S=23, R=23, M=100000, ifdef(`UUCPAUTH',`
	P=/usr/lib/authorise, A=authorise uucp $g $h /usr/bin/',`
	P=/usr/bin/uux, A=')uux - -r -gA $h!rmail ($u)

#
#  Addresses are converted back to uucp style.
#
S23
R<$+>			$@<$1>			return transport addr

R$+@$+			$:$>8$1@$2		convert to uucp style
R$+!$+			$@$1!$2			address ok
R$+			$@UUCPNAME!$1		add uucp domain name')')

ifdef(`JANETNAME',`
###################################################################
###
###		Janet Mailer specification
###
###################################################################

ifdef(`JANETHHSEND',`
Mniftp, F=nsmFDMxu, S=24, R=24, M=100000, ifdef(`JANETAUTH',`
	P=/usr/lib/authorise, A=authorise janet $g $h /usr/lib/x25/',`
	P=/usr/lib/x25/hhsend, A=')hhsend $h $u',`
Mniftp, F=SnsmFDMxu, S=24, R=24, M=100000, ifdef(`JANETAUTH',`
	P=/usr/lib/authorise, A=authorise janet $g $h /usr/lib/niftp/',`
	P=/usr/lib/niftp/ni_send, A=')ni_send -f $g $h $u')

S24
R<$+>			$@<$1>			return transport addr

R$+@$+			$@$>9$1@$2		RFC822 -> NRS style

R$+			$:$1@JANETNAME		add janet domain name
R$+@$+			$@$>9$1@$2		RFC822 -> NRS style')

ifdef(`NEWSNAME',`
###################################################################
#####
#####           News Mailer specification
#####
###################################################################
ifdef(`NEWSRELAYED',`
# This host forwards all news messages to a relay',`
Mnews, P=/usr/lib/news/mail-news, F=nlsmFDMPuh, S=25, A=inews -f $g -n $u -h

S25
R<$+>			$@<$1>			return transport addr
R$+@$+			$@$1@$2			address ok
R$+			$@$1@NEWSNAME		add local domain')')

ifdef(`CSNETNAME',`
###################################################################
###
###		CSNet PhoneNet Mailer specification
###
###################################################################

Mpmdf, F=nsmFDM, S=26, R=26, M=100000, ifdef(`CSNETAUTH',`
	P=/usr/lib/authorise, A=authorise csnet $g $h /usr/local/lib/pmdf/',`
	P=/usr/local/lib/pmdf/pmdf-submit, A=')pmdf-submit -f $g $u

S26
R<$+>			$@<$1>			return transport addr

R$+@$+			$@$1@$2			address ok
R$+			$@$1@CSNETNAME		add csnet domain name')

ifdef(`DECNETNAME',`
###################################################################
#####
#####           DECNET Mailer specification
#####
###################################################################

Mmail11, F=nsmFDM, S=27, R=27, M=100000, ifdef(`DECNETAUTH',`
	P=/usr/lib/authorise, A=authorise decnet $g $h /usr/bin/',`
	P=/usr/bin/mail11, A=')mail11 $f $x $h $u

S27
R<$+>			$@<$1>			return transport addr
R$+@$+			$:$>8$1@$2		convert to uucp style
R$+!$+			$1::$2			and then to decnet style
#R$+			$@DECNETNAME::$1	add local decnet name')

ifdef(`XEROXNAME',`
###################################################################
#####
#####           Xerox Ethernet Mailer specification
#####
###################################################################

Mxerox, F=nsmFDSEuX, S=28, R=28, M=100000, ifdef(`XEROXAUTH',`
	P=/usr/lib/authorise, A=authorise xerox $g $h /usr/lib/',`
	P=/usr/lib/mxerox, A=')mxerox $u

S28
R$+@$+                  $@$1@$2                 address ok
R$+			$@$1@XEROXNAME		add local domain')
version.m4      596036916   548   22    100444  4451      `
#
#	@(#)version.m4	UK-2.1 sendmail configuration		18/11/88
#

#
#	UK-2.1  18/11/88	jim + jem
#	Ruleset 16 general rules replaced by "wildcard" matching rules
#	generated from the tables.
#	Added support for news channel and decnet and xerox mailers.
#	Janet channel can use niftp or hhcp. Removed support for bitnet mail.
#	Included various BSD4.3 options. Defined optional long Received header.
#	Catch configuration errors in S0.  Miscellaneous bugs fixed.
#
#	UK-2.0	28/8/88		jim
#	COMMENTS:
#	Experimental version. Ruleset 15 now returns normalised local domain
#	name ($J). This is called by S3; S0 now calls S3 iff domain is $J.
#	S1 strips $J so mailer specific local domain is always added.
#	Domain expansion (S11) is reworked - only explicit table entries are
#	expanded making the sorting simpler and more correct.
#	Support for nameserver and ida database lookup added.
#	Reworked handling of transport addresses through header rulesets -
#	they are enclosed in angle brackets which are removed in S4 (or S3). 
#	Received/Via fields now generated according to whether $s or $S is set.
# 	Added support for TCP channel (for Internet).
#	Janet channel now uses niftp rather than hhcp. Domain literal
#	support now moved to TCP channel (niftp doesn't allow them).
#
#	UK-1.4a 9/10/86		jim
#	COMMENTS:
#	Band-aid for BSD4.3 (& Sun 3.0). The transport address goes through
#	the header rulesets (big sigh) so have to do a kludge for uucp.
#	$a -> $b in Resent-Date field: this seems to be what you want.
#	change to $q: don't emit angle brackets if full name is unknown.
#	Applied similar BSD4.3 band-aid to the janet channel on 6/5/87.
#
#	UK-1.4  12/2/86		jim
#	COMMENTS:
#	Added code to catch unknown local subdomains as errors.
#	Added support for CSNet PhoneNet mailer.
#	Merged barpa and buucp mailers into one bsmtp mailer (bitnet).
#	Delay use of bitnet general rule in the same way as for janet.
#	Added Message-Id header specification; generated for non-local mail.
#	Changed local mailer specification to give fully qualified names
#	except on uucp bang paths where domain is stripped.
#	Changed "-f" argument to muucp from $f to $g.
#	Changed "h" mailer flag to "u" in Janet mailer.
#
#	UK-1.3  8/9/85		jim
#	COMMENTS:
#	Delay use of general rule for janet mailer until no specific
#	rule matches in uk domain.
#	NRS domain order handling now ifdef-ed NRSFORMAT; thus separating
#	it from Janet mailer specific code
#	Domain literals now accepted & passed to Janet mailer.
#	Set "metoo" option. Helps with multihost sites that talk SMTP.
#	Set "x" & "X" options (load averages) for newer versions of sendmail
#
#	UK-1.2	9/6/85		jim
#	COMMENTS:
#	Bug fix: SMTP won't talk between local hosts of a multihost site.
#	use $J to define site domain name, $j is the host domain name.
#	Renumbered rulesets:
#		Rulesets  0 -  4 :	basic rulesets
#		Rulesets  5 -  9 :	address conversions
#		Rulesets 10 - 13 :	domain name handling
#		Rulesets 15 - 17 :	channel routing
#		Rulesets 20 - 25 :	mailer specifications
#	Reorganised channel routing to allow multiple names for local domain
#	and to retry the main routing ruleset, with higher level domains
#	when no match is found, before trying top level domain relaying.
#	Each mailer channel can now have a different local domain name
#	(default is official name - $J).  Multihost stuff simplified.
#	New uucp front end program replaces uux. Produces the correct from line.
#	
#
#	UK-1.1	22/4/85		jim
#	COMMENTS:
#	Changed janet rules in ruleset 3 to cope properly with domain expansion.
#	Changed output of ruleset 9 (channel ruleset) so that ruleset 0
#	can parse multiple-token hostnames.  Support files for janet added.
#	Renamed janet mailer to "hhcp". Added 'n' mailer flag to prog mailer.
#	Added ruleset 8 to detect and convert NRS style domains to 822 style.
#
#	UK-1.0	26/3/85		jim
#	COMMENTS:
#	Some rearranging. Removed ruleset 8 (path optimisation) as it
#	optimised munged addresses away completely! 
#	Ruleset 4 ensures an '@' in Percent style address.
#	Uucp ruleset rewritten to get as close to the uucp transmission
#	standard as sendmail allows.
#
#	HW-5.0	26/2/85		jim
#	COMMENTS:
#	major restructuring: rewrote ruleset 3 which now converts
#	all addresses to one style. Added bitnet mailer and ether mailer
#	Rewrote all the mailer specs. Various other cleanups.
#
#	HW-4.0	5/12/84		jim
#	COMMENTS:
#	This is a complete rewrite based on some ideas borrowed from
#	mmdf.
#

\Rogue\Monster\
else
  echo "Will not over-write ./Rules.a"
fi
chmod 444 ./Rules.a
if [ `wc -c < ./Rules.a` -ne 20922 ]
then
echo 'Got' `wc -c < ./Rules.a` ', Expected ' 20922
fi
if `test ! -s ./Domcheck`
then
echo "Writing ./Domcheck"
cat > ./Domcheck << '\Rogue\Monster\'
#!/bin/sh
#
#	Domcheck - Check UK-Sendmail domain data files for obvious blunders
#
#	Copyright (c) 1988 Jem Taylor
#

if [ $# -lt 1 ]
then	echo	usage: $0 files...
	exit
fi

for i in $@
do
	sed -e 's/#.*//' -e '/^$/d' $i | awk '
BEGIN	{ bad=0; ok=1; format=ok }
/%s[ 	.]/||/%s$/ { printf "%s: line %d - %%s has no meaning in DOMAIN data\n", file, NR 
	  format=bad
	}
NF>2	{ printf "%s: line %d - %d columns of data\n", file, NR, NF
	  format=bad
	}
/[][<>|\\*(){}~`";:,?\/]/ {
	  printf "%s: line %d - bogus character\n", file, NR
	  format=bad
	}
	{ for ( i=1 ; i <=2 ; i++ )
	  {	if (substr($i,1,1)==".")
	  	{	printf "%s: line %d - leading dot column %d\n",\
					file, NR, i
			format=bad
		}
		if ( substr($i,length($i),1) == "." )
		{	printf "%s: line %d - trailing dot column %d\n",\
					file, NR, i
			format=bad
		}
	  }
	  if ( format == bad )
	  {	print "	" $0
	  	format=ok
	  	errval++
	  }
	}
END	{ if ( errval > 0 )
		printf "%d errors detected\n", errval
	  exit errval
	} ' file=$i -
done

# delete everything from first whitespace or first dot in domain declarations
duplicates=`sed -e '/^#/d' -e '/^$/d' $@ \
| awk '{ if (index($1,".")==0 && $1==substr($2,1,index($2,".")-1)) print $2 }'\
| sed -e 's/[. 	].*//' | sort | uniq -d`

if [ -n "$duplicates" ]
then
	echo '
================ Domain entries duplicated or conflicting ================'
	for i in $duplicates
	do
		echo "
--------------		$i		--------------"
		grep "^$i[. 	]" $@ | sed 's/:/:	/'
	done
	exit 99
fi
\Rogue\Monster\
else
  echo "Will not over-write ./Domcheck"
fi
chmod 555 ./Domcheck
if [ `wc -c < ./Domcheck` -ne 1491 ]
then
echo 'Got' `wc -c < ./Domcheck` ', Expected ' 1491
fi
if `test ! -s ./Chncheck`
then
echo "Writing ./Chncheck"
cat > ./Chncheck << '\Rogue\Monster\'
#!/bin/sh
#
#	Chncheck - syntax check UK-Sendmail channel tables for obvious errors.
#	Returns the number of errors found.
#
#	Copyright (c) 1988 Jem Taylor
#


if [ $# -lt 1 ]
then	echo	usage: $0 files...
	exit
fi
for i in $@
do
	sed -e 's/#.*//' -e '/^$/d' $i | awk '
BEGIN	{ bad=0; ok=1; format=ok }
NF>2	{ printf "%s: line %d - %d columns of data\n", file, NR, NF
	  format=bad
	}
/[][<>|\\(){}~`";:,?\/]/ {
	  printf "%s: line %d - bogus character\n", file, NR
	  format=bad
	}
	{ for ( i=1 ; i <=2 ; i++ )
	  {	if (substr($i,1,1)==".")
	  	{	printf "%s: line %d - leading dot column %d\n",\
					file, NR, i
			format=bad
		}
		if ( substr($i,length($i),1) == "." )
		{	printf "%s: line %d - trailing dot column %d\n",\
					file, NR, i
			format=bad
		}
	  }
	  if ( format == bad )
	  {	print "	" $0
	  	format=ok
	  	errval++
	  }
	}
END	{ if ( errval > 0 )
		printf "%d errors detected\n", errval
	  exit errval
	} ' file=$i -
done

#janet chan tends to blow this up because top domain is at front - adjust
#the 'ignore' list to suit your janet.chn; if you have no janet chan then
#delete the ignore list altogether. If you prefer, just exit here:
#exit

# delete everything after the first whitespace
duplicates=`sed -e '/^#/d' -e '/^$/d' -e 's/[ 	].*//' $@ | sort | uniq -d`

exitcode=0
if [ -n "$duplicates" ]
then	for i in $duplicates
	do	case $i in
		uk|com|edu|us|ie|irl|nz|au|gov|uucp|arpa|dk|se|no|earn)
			;;
		*)	echo "
---------	$i : duplicate or conflict	---------"
			egrep "^$i\$|^$i[ 	]" $@ | sed -e 's/:/:	/'
			echo
			exitcode=99
			;;
		esac
	done
	exit $exitcode
fi
\Rogue\Monster\
else
  echo "Will not over-write ./Chncheck"
fi
chmod 555 ./Chncheck
if [ `wc -c < ./Chncheck` -ne 1596 ]
then
echo 'Got' `wc -c < ./Chncheck` ', Expected ' 1596
fi
if `test ! -s ./Install.sh`
then
echo "Writing ./Install.sh"
cat > ./Install.sh << '\Rogue\Monster\'
#!/bin/sh
# install a new sendmail configuration file on a host on the network
# produce a freeze file and start a new daemon
# if -f is specified, a freeze file is not made.
# if -n is specified, only the daemon is started.
# if -s is specified, the remote host is assumed to have SysV ps.


dofreeze=true
docopy=true
bsd=true
verbose=+x

while [ $# -ge 1 ]
do
	case $1 in
	-f)	dofreeze=false
		;;
	-n)	docopy=false
		;;
	-s)	bsd=false
		;;
	-v)	verbose=-x
		;;
	*)	host=$1
		if [ $# -eq 2 ]
		then
			file=$2
			shift
		else
			file=$1.cf
		fi
		break
		;;
	esac
	shift
done

if [ $# -ne 1 ]
then
	echo 'usage: Install.sh [-f] [-n] [-s] host [file]'
	exit 1
fi


if $docopy
then
#
#	copy configuration file.  If successful, freeze it; otherwise
#	the host is probably down - remove the cf file and quit
#
	if (set $verbose; rcp $file $host:/usr/lib/sendmail.cf)
	then
		if $dofreeze
		then
			(set $verbose; rsh $host -n /usr/lib/sendmail -bz)
		fi
	else
		echo "$0: failed for $host - quitting"
		exit 1
	fi
fi

#
# kill off current sendmail daemon and start a new one
#
if $bsd
then
	pid=`rsh $host -n ps -ax | awk ' { if ($5 == "/usr/lib/sendmail" && $6 == "-bd") print $1 }'`
else
	pid=`rsh $host -n ps -ef | awk '/[0-9]:[0-9][0-9] \/usr\/lib\/sendmail -bd/ { print $2 }'`
fi

if [ "$pid" -gt 1 ]
then
	(set $verbose; rsh $host -n kill $pid)
	sleep 1
fi

(set $verbose; rsh $host -n /usr/lib/sendmail -bd -q1h)

exit 0
\Rogue\Monster\
else
  echo "Will not over-write ./Install.sh"
fi
chmod 555 ./Install.sh
if [ `wc -c < ./Install.sh` -ne 1425 ]
then
echo 'Got' `wc -c < ./Install.sh` ', Expected ' 1425
fi
echo "Finished archive 1 of 4"
exit