GaTech Sendmail (Part 2 of 3)

sources-request at panda.UUCP sources-request at panda.UUCP
Mon Oct 14 23:21:25 AEST 1985


Mod.sources:  Volume 3, Issue 24
Submitted by: Gene Spafford <ihnp4!gatech!spaf>


#! /bin/sh

# Make a new directory for these sources, cd to it, and run kits 1 thru 3 
# through sh.  When all 3 kits have been run, read README.

echo "This is GaTech Sendmail kit 2 (of 3).  If kit 2 is complete, the line"
echo '"'"End of kit 2 (of 3)"'" will echo at the end.'
echo ""
export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
echo Extracting overview.ms
cat >overview.ms <<'!STUFFY!FUNK!'
.TL
Mail Handling at Gatech
.br
Revision II
.AU
Gene Spafford
.AI
School of Information and Computer Science
Georgia Institute of Technology
23 September 1985
.PP
Site "gatech" is running a "smart" version of sendmail.  I have 
hacked at the sendmail configuration files extensively, and although
they are not yet doing 100% of what I want, they seem to work pretty well
and handle our many (sometimes unusual) mail needs.
What follows are brief descriptions of what happens to various bits of
mail passing through our site. 
.PP
There have been some changes since the last time I circulated this
document.  Most of the changes have been inspired (?) by the changes
to sendmail done at Rutgers which allow "sendmail" to distinguish
the source of incoming mail with mixed syntax addresses (e.g., a!b at c),
and which rewrite the names of Internet hosts into the preferred form
(as given in the /etc/hosts table, derived from NIC data).
.NH 1
Why
.PP
Site "gatech" is directly on the uucp network
(with over 75 contacts and acting as a de facto name server for a
"southeast US domain"), the CSNet, and we serve as gateway for
our local networks.  We also have network traffic with some other
major networks, and we might possibly get BITNET and ARPA access in
the not-too-distant future, from "gatech" or some other campus machines.
We'd like to have as complete and robust
a mailing environment as possible.  At the same time, we'd like
to minimize our current phone bills as they are related to UUCP mail 
traffic.
.NH 1
Routing
.NH 2
Known Domains
.PP
Currently, there is considerable effort going on to identify and
establish domains for mailing.  Some of these domains are already
established, if only in a de facto manner.  Our sendmail
currently recognizes the following well-known domains: ARPA, CSNET,
GOV, EDU, COM, MIL, ORG, NET,
UUCP, BITNET, DEC, and MAILNET.  The following 
are also recognized when used as top-level domains:
GTNET (local to Georgia Tech), OZ (the Australian network),
TEK (recognized internal to Tektronix), and SDC (with sdcrdcf as the gateway).
.PP
There are a number of other "domains" that are recognized when used
in a second-level position within a uucp address.  That is, we
recognize person at site.ATT.UUCP as something that should be
directed to cbosgd via uucp for further resolution.  This recognition
is done by building psuedo-sites into the uucp routing database
based upon the data distributed by the uucp map project.  
Among domains recognized like this are NCAL, SCAL, ATL, ATT, UK, and
so on; the list may change based on updates to the map.
(As an aside, at the time of this writing, "gatech" is one of
the regional repositories of the current map, and we get automatic
updates whenever the "real" map gets changed.)
.PP
In the following descriptions, any of the above can be used in
place of a "DOMAIN" specifier.
.NH 2
user at host[.DOMAIN] -and- user%host[.DOMAIN]
.PP
If mail comes in addressed specifically to one of the known domains,
it is routed as described in the next section without any further
changes.  If the domain is not given, an attempt is made to derive
the domain based on available lists of host names and aliases,
and then routed as described in the next section.  If no host/domain
match can be found, the mail is returned with an error stating this.
.NH 3
Domain Derivation
.PP
Host derivation is attempted in the following order:  First, the
host is checked to see if it is in the GTNET domain.  Next, the
host is checked to see if it is a host one hop away via UUCP.  Next,
the host is checked against all CSNET sites.  Then it is checked
against all Arpa/Internet sites. Next, it is checked against the list of
known MAILNET hosts. Then it is checked against the list of all (other) known
UUCP sites. Then it is checked against the list of
known BITNET hosts.  Finally, it is checked against the list
of known DEC E-net sites.  
.PP
This kind of checking is not 100% accurate because our lists are not
always up-to-date.  In particular, the Arpa list is updated infrequently
due to the fact that we aren't actually on the Arpanet, and there is no
list of DEC net sites available outside of DEC (we make due with
gleaning names from posted news articles and exchanges with other sites
interested in compiling such a list).
.NH 3
Collisions
.PP
If the same hostname exists in more than one domain, the first match
found will be the one used.  Qualification of the address with an
explicit domain specifier will ensure that the mail goes to the
correct host (when routed through gatech).  That is, the domain
is considered to be the specifer for routing and if one is not
explicitly provided (or implicitly, as in the case of "!" notation),
then an attempt to made to guess a domain.
.NH 2
host1!host2!host3...!hostn!user
.PP
Starting with "hostn" and working backwards to "host1" our mailer
will attempt to find a host listed in our master UUCP path database.
This database is generated using pathalias at least weekly based on the latest
version of the uucp maps.  If a match is found at "hostk", then the 
address is rewritten to be "<path to hostk>!hostk!...hostn!user"
and then mailed via UUCP.  Such addresses are NEVER routed over
any other network, unless "hostn" is recognized to be a GTNET
host, in which case our internal transport mechanism is invoked.
.PP
There is NO way at present to force a path on UUCP mail through "gatech".
This is perhaps a "not very good thing" but I can't come up with a good
way to work in explicit paths.  The map data is generally very good
and I have observed very, very few failures since we first started
doing this rewriting about 6 months ago.  If this presents a
major problem for someone, let me know and I'll see what I can work out.
.NH 2
host1!host2!host3...!hostn!user at site[.DOMAIN]
.br
host1!host2!host3...!hostn!user%site[.DOMAIN]
.PP
This one diverges somewhat from the standard (RFC822 et.al.).  
The way these addresses get treated is based on the way the mail
gets into our "sendmail."  If the message originates on any of the
local (GTNET) machines, or if it comes in via PMDF from CSNet, then
the mail is routed to "site" for eventual delivery to host1!...hostn!user.
Mail coming in via a UUCP link with a mixed-mode address like this will
have the mail routed via uucp to hostn for eventual delivery to
user at site.  Thus, if one of our neighbors, such as someone at akgua,
were to send mail to us addressed as seismo!person at ucbvax.ARPA, we would
send the mail to seismo via uucp and present it to their "rmail"
program as "rmail person at ucbvax.ARPA".
.PP
On the other hand, should someone on gitpyr send mail addressed
as seismo!person at ucbvax.ARPA, it would arrive at Gatech via SMTP and
then be sent to CSNet-relay via PMDF for delivery to site "ucbvax" with
a request to be delivered to "seismo!person" relative to that site.
In most cases, depending on the sites involved,
this kind of treatment would result in the mail failing.  The sendmail
configurations I have created for all the local GTNET sites are such
that it should not be required to specify such an address.  Simply
mailing to person at site should see the correct address and network
transport mechanism chosen.  The Usenet "news" programs on most of these
sites have been built to use the Internet-style of address when
mailing replies, so there should be few cases of users even seeing mixed
mode addresses presented to them (mail passing through any of the mailers
gets rewritten to show a consistent format).
.NH 2
user%site1%site2%site3
.PP
Addresses of this format get turned into user%site1%site2 at site3,
and an appropriate routing is provided to "site3," if known.
.NH 2
Other network characters
.PP
The ":" delimiter gets turned into "!" symbols in any address
presented to our sendmail.
The "^" delimiter gets turned into "!" also.  Addresses of the
form "site=user" get turned into "user at site.BITNET" by convention.
.NH 1
Errors
.PP
I have tried to trap all possible errors and generate return mail
with meaningful messages.  
If you get errors you don't know how to interpret, please contact me.
.NH 1
Source
.PP
I posted an ancestor of my current sendmail files to "mod.sources" a
few months ago.  If these latest versions appear stable, I will post
them to the same place.  If you'd like a copy right away, let me know.
This includes the sendmail files for all the local GTNET machines, and
the source for my "uumail" program which sits between sendmail and
uux.
!STUFFY!FUNK!
echo Extracting uumail.c
cat >uumail.c <<'!STUFFY!FUNK!'
/* uumail.c --- uucp remailer
 *	EHS 4/2/85
 *      Added rebuild sentinel and better error handling 10/13/85
 *
 * Compile as:
 *	cc -O -s uumail.c -ldbm -o uumail
 *
 *  Usage:
 *    usually called from sendmail in the following form:
 *      uumail -f from addr < message
 *    "from" is the address of the sender, and is passed to "uux"
 *       in case of a remote error
 *    "addr" is an address in the following form:
 *		site!site!site!user
 *     and "user" can take on any form not containing a "!"
 *
 *     If a "-D" is used instead of a "-f", no mail will be sent
 *     and various bits of diagnostic info will be printed to the
 *     standard error output.  Messages that would normally be
 *     printed at the console are also printed to stderr, in this
 *     case.  The body of the message is also dumped to stderr.
 *
 *     At least one "!" MUST be present in the address or else it will 
 *     be considered an error.
 *
 *    The address is rewritten for the first applicable site
 *    found in the database.  If the path cannot be rewritten,
 *    an error code is returned along with a message indicating
 *    the problem.
 *
 *    If the special sentinel value of @@@ is not present in the
 *    database, then it is assumed that the database is being
 *    rebuilt and the requesting process is blocked for TIMEOUT
 *    (default = 180) seconds.  If, after 5 such blocks, the
 *    sentinel is not present, an error message is logged to
 *    the console, and the error code EX_TEMPFAIL is returned.
 *    The same is true if the dbm files cannot be initialized.
 *
 *    Note:
 * 	The "uux" flags given below are for 4.3 BSD uucp and
 *	may not exist for your version of uucp.  Note especially
 * 	that the "-L" flag may not be present in earlier versions
 *	(meaning to crank up uucico for a local call, otherwise
 *	just queue it).
 *
 *    Special defines:
 *      PATHFILE is the basename of the dbm path database.
 *      LOGF  if defined is where a log of uucp mail is kept
 *      TIMEOUT is the sleep(2) time, in seconds, to wait
 *         if the database is unavailable or incomplete.
 *      CONSOLE is the pathname of the file to report major errors
 *      MYSITE is the site name to be used in reporting errors
 *	   via returned mail; if not defined, the sitename is
 * 	   derived from a call to gethostname(2)
 *	UUX is a sprintf(3) format string used to remotely execute
 *	   the rmail command on the next system.
 *      SENTINEL is the special "sitename" to look for in the
 *	   path database to indicate a complete database
 */

#include <ctype.h>
#include <dbm.h>
#include <stdio.h>
#include <sysexits.h>

#ifndef PATHFILE
#define PATHFILE  "/usr/lib/mail/uucp.hosts"
#endif PATHFILE

#ifndef CONSOLE
#define CONSOLE   "/dev/console"
#endif CONSOLE
FILE *console;

#ifndef TIMEOUT
#define TIMEOUT ((unsigned) 180)
#endif TIMEOUT

#ifndef UUX
#define UUX "/usr/bin/uux -p -a%s -L -gM %s!rmail \\(%s\\)\n"
#endif UUX

#ifndef SENTINEL
#define SENTINEL "@@@"
#endif SENTINEL

extern char *malloc (), *rindex (), *index ();
extern char *strcpy (), *strcat ();
extern int strlen ();
extern  FILE *popen ();

datum key, result;
char    workbuf[512];
char   *destination,
       *sender;

int     debug;

#ifdef LOGF
FILE	*logfile;
#endif LOGF


main (argc, argv)
int     argc;
char  **argv;
{
    register char  *stp,
                   *rtp;
    int     indx, retval;
    extern  void die (), checkpath ();


    destination = argv[3];	/* given destination (and user) */
    sender = argv[2];		/* given sender */

    if (argc != 4)
	die ("called with incorrect number of arguments.", EX_USAGE);
    debug = (argv[1][1] == 'D');

    console = fopen (CONSOLE, "a");
    if ((console == NULL) || debug)
	console = stderr;

#ifdef LOGF
    logfile = fopen (LOGF, "a");
    if (logfile == NULL)
    {
	fprintf (console, "\n*** uumail: Unable to open logfile %s\n", LOGF);
	logfile = console;
    }
    fprintf (logfile, "%s\t%s\t", sender, destination);
#endif LOGF

    for (indx = 0; indx < 5; indx++)
    {
	if ((retval = dbminit (PATHFILE)) >= 0)
	    break;
	
	if (debug)
	    fprintf (stderr, "Database unavailable.  Sleeping.\n");
	sleep (TIMEOUT);
    }

    if (retval < 0)
	die ("could not open routing database files.", EX_TEMPFAIL);

    key.dptr = SENTINEL;
    key.dsize = strlen (SENTINEL) + 1;
    for (indx = 0; indx < 5; indx++)
    {
	result = fetch (key);
	if (result.dsize > 0)
	    break;
	
	if (debug)
	    fprintf (stderr, "Database incomplete.  Sleeping.\n");
	sleep (TIMEOUT);
    }
    if (result.dsize <= 0)
	die ("routing database files incomplete or truncated.",
		EX_TEMPFAIL);


/* Now we back up through the address until we find a site we
 * know how to reach.  If we don't find any, it's an error.
 */

    strcpy (workbuf, destination);

    if (!(rtp = rindex (workbuf, '!')))
	die ("address in improper format.", EX_DATAERR);

    *rtp = '\0';
    while (stp = rindex (workbuf, '!'))
    {
	checkpath (rtp + 1, stp + 1, (int) (rtp - stp));
	*rtp = '!';
	rtp = stp;
	*rtp = '\0';
    }
    checkpath (rtp + 1, workbuf, (int) (rtp - workbuf) + 1);

 /* If we got to here, we don't have a path */

    *rtp = '!';
    die ("Unable to find path to any host in pathname.", EX_NOHOST);
}


/*  This routine does all the work.  If it finds a path it immediately
 *  will go ahead and do the mailing and exit.
 */

void checkpath (user, site, len)
char   *user,
       *site;
int     len;
{
    FILE * pipfd;
    int     comlen;
    char   *address,
           *restol,
           *command;

    key.dptr = site;
    key.dsize = len;
    result = fetch (key);
    if (result.dsize <= 0)
	return;	   /* result <= 0 implies no match */

 /* rewrite here */
    comlen = strlen (user) + result.dsize;
    address = malloc ((unsigned) comlen);
    if (address == NULL)
	die ("malloc cannot get memory for new address.\n", EX_SOFTWARE);

    sprintf (address, result.dptr, user);
#ifdef LOGF
    fprintf (logfile, "%s\n", address);
#endif LOGF
    comlen = strlen (address) + strlen (UUX) + 4;
    command = malloc ((unsigned) comlen);
    if (command == NULL)
	die ("malloc cannot get memory for uux command line.\n", EX_SOFTWARE);

    if ((restol = index (address, '!')) != NULL)
	*restol++ = '\0';
    sprintf (command, UUX, sender, address, restol);
    if (debug)
    {
	fprintf (stderr, "Command that would be executed: %s\n", command);
	pipfd = stderr;
    }
    else
    {
	pipfd = popen (command, "w");
	if (pipfd == NULL)
	    die ("cannot open pipe with popen(3).", EX_SOFTWARE);
    }

    while (fgets (workbuf, sizeof (workbuf), stdin))
	fputs (workbuf, pipfd);

    comlen = debug == 0 ? pclose (pipfd) : 0;
    if (comlen)
    {
	sprintf (workbuf, "execution of uux returned with error status %d",
	    comlen);
	die (workbuf, EX_UNAVAILABLE);
    }

    exit (EX_OK);
}


void die (message, errcode)
char   *message;
int     errcode;
{
#ifdef MYSITE
    char   *mysite = MYSITE;
#else
    char    mysite[64];
    gethostname (mysite, 64);
#endif


#ifdef LOGF
    fprintf (logfile, "Error: %s\n", message);
#endif LOGF

    fprintf (console, "\n\07*** Error in uumail!\n");
    fprintf (console, "    %s\n", message);
    fprintf (console, "    Mail from %s to %s being returned.\n\n", sender,
	    destination);

    fprintf (stderr, "Mailer at \"%s\": %s\n", mysite, message);
    exit (errcode);
}
!STUFFY!FUNK!
echo Extracting base.m4
cat >base.m4 <<'!STUFFY!FUNK!'
############################################################
#
#  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 Gatech per se.
#
#  $Header: base.m4,v 5.1 85/10/13 20:45:34 spaf Release $
#
############################################################

include(version.m4)

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

# my name
DnMAILER-DAEMON
# UNIX header format
DlFrom $g  $d
# delimiter (operator) characters
Do.:%@!^=/[]
# format of a total name
Dq$?x$x $.<$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
# (don't) connect to "expensive" mailers
Oc
# temporary file mode
OF0600
# default GID
Og1
# location of help file
OH/usr/lib/sendmail.hf
# log level
OL2
# default messages to old style
Oo
# 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
# Queue when we're busy (x) and refuse SMTP when really busy (X)
Ox15
OX20
# default timeout interval
OT5d
# time zone names (V6 only)
OtEST,EDT
# default UID
Ou1
# wizard's password
OWa/FjIfuGKXyc2

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

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

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

Troot
Tdaemon
Tuucp
Tnetwork

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

H?P?Return-Path: <$g>
HReceived: $?sfrom $s $.by $j ($v/$V)
	id $i; $b
H?D?Resent-Date: $a
H?D?Date: $a
H?F?Resent-From: $q
H?F?From: $q
H?x?Full-Name: $x
HSubject:
HPosted-Date: $a
# H?l?Received-Date: $b
# H?M?Resent-Message-Id: <$t.$i@$j>
H?M?Message-Id: <$t.$i@$j>

###########################
###   Rewriting rules   ###
###########################


################################
#  Sender Field Pre-rewriting  #
################################
S1

###################################
#  Recipient Field Pre-rewriting  #
###################################
S2

#################################
#  Final Output Post-rewriting  #
#################################
S4

R@			$@				handle <> error addr

# externalize local domain info
R$*<$*LOCAL>$*		$1<$2$D>$3			change local info
R$*<$+>$*		$1$2$3				defocus
R$*$=S:$*		$1$2!$3
R@$+:$+:$+		$@@$1,$2:$3			<route-addr> canonical

# delete duplicate local names -- mostly for arpaproto.mc
R$+%$=w@$=w		$1@$3				u%UCB at UCB => u at UCB
R$+%$=w@$=w.$=D		$1@$3.$D			u%UCB at UCB => u at UCB

# clean up uucp path expressions (some)
R$*!$*@$*.UUCP		$3!$1!$2

###########################
#  Name Canonicalization  #
###########################
S3

# handle "from:<>" special case
R<>			$@@				turn into magic token
R$*$=S:$=S$*		$1$3$4
R$*$=S!$=S$*		$1$3$4

# basic textual canonicalization
R$*<$+>$*		$2				basic RFC821/822 parsing
R$+ at $+		$1@$2				"at" -> "@" for RFC 822
R$*<$*>$*		$1$2$3				in case recursive

# make sure <@a, at b, at c:user at d> syntax is easy to parse -- undone later
R@$+,$+			@$1:$2				change all "," to ":"

# localize and dispose of domain-based addresses
R@$+:$+			$@$>6<@$1>:$2			handle <route-addr>

# more miscellaneous cleanup
R$+			$:$>8$1				host dependent cleanup
R$+:$*;@$+		$@$1:$2;@$3			list syntax

# Handle special case of received via uucp
R$-!$*			$:<$&r>$1!$2			check arriving protocol
R$-^$*			$:<$&r>$1!$2			both syntaxes
R<UUCP>$-!$*		$@$>6$2<@$1.UUCP>		if via UUCP, resolve
R<$*>$*			$2				undo kludge
R$+@$+			$:$1<@$2>			focus on domain
R$+<$+@$+>		$1$2<@$3>			move gaze right
R$+<@$+>		$@$>6$1<@$2>			already canonical

# convert old-style addresses to a domain-based address
R$+%$+			$:$1<@$2>			user%host
R$+<@$+%$+>		$1%$2<@$3>			fix user%host1%host2
R$+<@$+>		$@$>6$1<@$2>			leave

R$-:$+			$@$>6$2<@$1>			host:user
R$-.$+			$@$>6$2<@$1>			host.user
R$+^$+			$1!$2				convert ^ to !
R$-!$+			$@$>6$2<@$1.UUCP>		resolve uucp names
R$-=$+			$@$>6$2<@$1.BITNET>		resolve bitnet names
!STUFFY!FUNK!
echo Extracting MANIFEST
cat >MANIFEST <<'!STUFFY!FUNK!'
After all the sendmail kits are run you should have the following files:

Filename	Kit Description
--------	--- -----------
Files            1  Description of auxillary files in /usr/lib/mail
KEY              3  Describes some of the macros and classes we use.
MANIFEST         2  This file: directory of files.
Makefile         3  Processes all our files.
PATCHES          1  Some source code changes for sendmail and rmail
README           1  Description of what files are and what they do.
base.m4          2  "basic" information included with all configurations.
cirrus.mc        3  Master configuration file for gt-cirrus Clouds machine.
csether.m4       3  ICS ethernet definitions.
etherm.m4        3  Actual definition of the Ethernet mail "channel".
gatech.mc        3  Master configuration file for our main relay machine.
gitpyr.mc        3  Master configuration file for ICS/OCS Pyramid.
gt-cmmsr.mc      3  Master configuration file for MMR Vax.
gtbase.m4        3  Specifics for GT mail.
gtqo.mc          3  Master configuration for Physics Sun.
gtss.mc          3  Master configuration for Physics Sun.
localm.m4        3  Actual definition of the "local" mail channel.
nimbus.mc        3  Master configuration for gt-nimbus Clouds machine.
overview.ms      2  A description of mail routing and address munging
pmdfm.m4         2  Definition of the pmdf mail "channel".
short2.m4        3  Short ruleset 0 used by non-ICS sites.
short3.m4        3  Short ruleset 0 used by Physics sites (Suns on ethernet).
shortzero.m4     3  Short ruleset 0 used in ICS department sites.
stratus.mc       3  Master configuration file for gt-stratus Clouds machine.
uucpm.m4         3  Definition of the uucp mail "channel".
uumail.c         2  Source for the uumail program (read the comments at the top)
uumail.m4        3  Definition of the uucp optimizing mailer used on "gatech"
version.m4       3  Define the sendmail version.
zerobase.m4      3  Machine independent preamble for ruleset 0.
!STUFFY!FUNK!
echo Extracting pmdfm.m4
cat >pmdfm.m4 <<'!STUFFY!FUNK!'
############################################################
############################################################
#####
#####		PMDF Phonenet Channel Mailer specification
#####
#####	$Header: pmdfm.m4,v 5.1 85/10/13 20:46:01 spaf Release $
#####
############################################################
############################################################

Mpmdf,	P=/usr/local/lib/pmdf/pmdf-submit,	F=mDsFSn,	S=17, R=17,
	M=65535, A=pmdf-submit -f $g $u
#
#	Notice that the PMDF mailer DOES NOT USE the host field. We
#	set this host field to "CSNET-RELAY" in all instances where
#	we call the PMDF mailer so as to be able to send one copy
#	of a letter with a number of recipients.
#

S17

# pass <route-addr>'s through
R<@$+>$*		$@<@$1>$2			resolve <route-addr>

# map colons to dots everywhere.....
R$*:$*			$1.$2				map colons to dots

# handle the simple case....
R$+<@$+.$=K>		$@$>18$1<@$2.$3>		user at host.ARPA
R$+<@$-.CSNET>		$@$1<@$2.CSNET>			user at host.CSNET

R$+<@LOCAL>		$@$1<@$R.CSNET>			local names
R$+<@$+.LOCAL>		$@$1%$2<@$R.CSNET>		local notes
R$+<@$*$=S>		$@$1%$2$3<@$R.CSNET>		more local hosts

# handle other external cases
R$+<@$=X>		$@$1<@$2.UUCP>
R$+<@$->		$@$1<@$2>	
R$+<@$+.$-.$=T>		$@$1%$2<@$3.$4>			approximate something
R$+<@[$+]>		$@$1<@[$2]>			already ok

# convert remaining addresses to old format and externalize appropriately
#  We try to do nifty things to uucp addresses first
R$+<@$-.UUCP>		$2!$1
R$+!$+!$+		$2!$3
R$+!$+			$@$2@$1.UUCP

R$-:$+			$@$1.$2<@$A>			convert berk hosts
R$+<@$+>		$@$1%$2<@$A>			pessmize
R$+			$:$1<@$R.CSNET>			tack on our hostname
R$+%$=A<@$A>		$1<@$2>				strip out unneeded relay


S18

R$*<$+>$*		$@$1<$%2>$3
!STUFFY!FUNK!
echo ""
echo "End of kit 2 (of 3)"
cat /dev/null >kit2isdone
config=true
for iskit in 1 2 3; do
    if test -f kit${iskit}isdone; then
	echo "You have run kit ${iskit}."
    else
	echo "You still need to run kit ${iskit}."
	config=false
    fi
done
case $config in
    true)
	echo "You have run all your kits.  Please read README."
	;;
esac
: I do not append .signature, but someone might mail this.
exit



More information about the Mod.sources mailing list