ast@cs.vu.nl (Andy Tanenbaum) (10/23/89)
: This is a shar archive. Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
: --------------------------- cut here --------------------------
PATH=/bin:/usr/bin:/usr/ucb
echo Extracting 'Makefile'
sed 's/^X//' > 'Makefile' << '+ END-OF-FILE ''Makefile'
X#
X# Makefile for UMAIL Mail Router (MINIX)
X#
X# Author: Fred van Kempen, MicroWalt Corporation
X#
X# Define WMAILER if the local mailer is W-MAIL.
X# This mailer understands the "-i filename" option,
X# and this works much faster than stdIO redirecting.
X#
XCFLAGS = -DMINIX -DWMAILER
X
XBIN = /usr/bin
X
XOBJS = ummain.s umtime.s umheader.s umconvert.s \
X umroute.s umsend.s umscanner.s
XSRCS = ummain.c umtime.c umheader.c umconvert.c \
X umroute.c umsend.c umscanner.c
XOTHERS = README umail.doc umail.cf umail Makefile uucp.h umail.h
X
Xumail: Makefile $(OBJS)
X cc -i -o umail $(OBJS)
X @chmem =16000 umail >/dev/null
X
Xinstall: umail
X @rm -f $(BIN)/umail $(BIN)/rmail
X @echo 'Copying files...'
X @cp umail $(BIN)/umail
X @echo 'Setting up links...'
X @ln $(BIN)/umail $(BIN)/rmail
X @echo 'Setting up permissions:'
X chown root.root $(BIN)/umail
X chmod 6555 $(BIN)/umail
X
Xshar:
X @shar -v -o umail.shar $(OTHERS) $(SRCS)
X
Xtar:
X @tar c umail.tar $(OTHERS) $(SRCS)
X
Xummain.s: umail.h ummain.c
X cc $(CFLAGS) -S ummain.c
X
Xumtime.s: umail.h umtime.c
X cc $(CFLAGS) -S umtime.c
X
Xumheader.s: umail.h umheader.c
X cc $(CFLAGS) -S umheader.c
X
Xumconvert.s: umail.h umconvert.c
X cc $(CFLAGS) -S umconvert.c
X
Xumroute.s: umail.h umroute.c
X cc $(CFLAGS) -S umroute.c
X
Xumsend.s: umail.h uucp.h umsend.c
X cc $(CFLAGS) -S umsend.c
X
Xumscanner.s: umscanner.c
X cc $(CFLAGS) -S umscanner.c
X
+ END-OF-FILE Makefile
chmod 'u=rw,g=r,o=r' 'Makefile'
set `wc -c 'Makefile'`
count=$1
case $count in
1429) :;;
*) echo 'Bad character count in ''Makefile' >&2
echo 'Count should be 1429' >&2
esac
echo Extracting 'README'
sed 's/^X//' > 'README' << '+ END-OF-FILE ''README'
X U-MAIL Remote Mail Transport Agent (MINIX)
X
X MicroWalt U-MAIL V2.5
X =====================
X
X
XThis archive contains the sources of the UMAIL Network Mailer
Xfor the MINIX operating system. It runs on most UNIXes as well.
X
XThe file 'umail' is the executable program, and 'umail.doc' is
Xthe (preliminary) documentation of the program.
XSee 'umail.cf' for configuration information.
X
XOf course, this program needs the presence of either UUCP or
XRSMTP to run properly...
X
XEnjoy!
X+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
X| MINIX User Group (Holland) UUCP: hp4nl!kyber!minixug!waltje |
X| c/o Fred van Kempen, or: minixug!waltje@kyber.UUCP |
X| Hoefbladhof 27 |
X| 2215 DV VOORHOUT |
X| The Netherlands "A good programmer knows his Sources" |
X+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
X
+ END-OF-FILE README
chmod 'u=rw,g=r,o=r' 'README'
set `wc -c 'README'`
count=$1
case $count in
852) :;;
*) echo 'Bad character count in ''README' >&2
echo 'Count should be 852' >&2
esac
echo Extracting 'umail.cf'
sed 's/^X//' > 'umail.cf' << '+ END-OF-FILE ''umail.cf'
X#
X# MicroWalt Corporation -- UMAIL Configuration File
X#
X# System: MINIX User Group Holland, minixug.nluug.nl
X# OS: MicroWalt Advanced MINIX 1.4B
X#
X# Author: F. van Kempen, MicroWalt Corporation
X#
X
X# These are some configuration variables for the
X# mailer. They define the working environment.
XBEGIN
X Organization := "MINIX User Group Holland, Netherlands"
X System := "minixug"
X Domain := "nluug.nl"
X TimeZone := "MET +0100"
X OldMailer := TRUE # We want V6 "From <user> <date>" lines
X Escape := TRUE # We can send all undeliverable mail
X # to another host.
XEND
X
X# The next table defines all the names under which
X# our system could possibly be adressed. It is used
X# to map domain adresses back to local adresses.
XNAMES BEGIN
X minixug.nluug.nl # Our official name
X minixug.nl # other possible names
X minixug.uucp # old-style UUCP name
X minixug # local name
XEND
X
X# This table defines the systems that we know of, and
X# what networking software to use to get to it.
X# 'TRUE' means, that the specified host understands
X# route-adressing (and can thus do things itself).
X# FALSE means that we have to give that host a ready-
X# to-run UUCP adress in bang-style.
XHOSTS BEGIN
X minixug := TRUE , $$ , "@" # Just local mail !
X kyber := FALSE , $$ , "@" # My UUCP host site
X archvax := FALSE , "rsmtp" , "<%s archvax!" # SMTP via Ethernet
XEND
X
X# This is the actual routing table.
X# It defines where mail for the various domains
X# should be sent to. Note, that domain "." is
X# the "default domain", which is used if no
X# matching domain can be found.
X# Format:
X#
X# DOMAIN := HOST , ROUTE
X#
XDOMAINS BEGIN
X aha.nl := kyber , htsa # Algemene Hogeschool Amsterdam
X edu := kyber , hp4nl # Educational Institutes Network
X nl := kyber , hp4nl # UUCP-Netherlands
X nluug := kyber , hp4nl # Dutch UNIX User Group Network
X nluug.nl := kyber , hp4nl
X uu.net := kyber , hp4nl # USA UUCP Network
X uucp := kyber , hp4nl # Old-style UUCP Network
X uunet := kyber , hp4nl # USA UUCP Network
X . := kyber , hp4nl # Default host
XEND
+ END-OF-FILE umail.cf
chmod 'u=rw,g=r,o=r' 'umail.cf'
set `wc -c 'umail.cf'`
count=$1
case $count in
2282) :;;
*) echo 'Bad character count in ''umail.cf' >&2
echo 'Count should be 2282' >&2
esac
echo Extracting 'umail.doc'
sed 's/^X//' > 'umail.doc' << '+ END-OF-FILE ''umail.doc'
XUMAIL(1) MINIX User's Manual UMAIL(1)
X
X
XNAME
X umail - electronic mail delivery agent.
X
XSYNOPSIS
X umail [-c <config> [-d] [-i <inputfile> [-n] <user>
X
XDESCRIPTION
X Umail is a semi-intelligent mail transporting program
X which knows something about Internet adresses and mail
X adress routing to other systems.
X It is used as a back-end to the Mailx program; which
X is used to read or create messages. Umail only takes
X care of the transportation of the message to other
X MINIX (or UNIX) systems through the available network
X software like UUCP and RSMTP.
X
X In restricted mode ('rmail') it functions as a message
X delivery program for incoming network mail.
X Networking programs like uucico(1) and rsmtp(8) execute
X the rmail(1) command to deliver a received message to
X the adressed user, or to forward the message to another
X system.
X
X The program has some command-line options, which are
X used to alter the "standard" behaviour of the program.
X The options are:
X
X -c <config> Debug; use 'config' as the configura-
X tion file instead of the standard
X one. This is sometimes useful when
X debugging the package.
X
X -d Debug; generate some useful output
X while working.
X
X -i <infile> Input; use file 'infile' as the mes-
X sage file instead of standard input.
X
X -n Now; call the networking delivery
X software immediately after queueing
X the message. Not recommended!
X
X The 'user' string identifies the network-adress of the
X user who is to receive the message. It can be any legal
X UUCP or Internet mail-adress.
X
XDELIVERY
X The Mailx program can serve as both a user agent and a
X local delivery agent. If Mailx sees that the adressed
X user is on the local system, it will do the delivery
X itself. No header (except for From, To and Subject) is
X added, and delivery errors will cause the message to
X be returned to the user as a file 'dead.letter'.
X
X Otherwise, if the specified adress is not local, the
X message is sent to the Remote Mailer on the system.
X
X
X
X -- 1 --
X
X
X
XUMAIL(1) MINIX User's Manual UMAIL(1)
X
X
X
X Usually, this is the rmail(1) command; programs like
X sendmail(8) or smail(1) (or links to them) are used as
X well. On MINIX systems, rmail(1) is a separate program.
X
X This small remote mailer knows something about UUCP, and
X how to interpret old-style UUCP (host!user) adresses.
X This works fine for most users, but it is sometimes nice
X to have a somewhat more intelligent mailer.
X Therefore, one could install Umail as a link to rmail(1)
X so that the mail(1) or Mailx(1) programs will never see
X the difference.
X
X These (more or less) intelligent mailers add a standard
X (RFC-822) header to the message, and then send it to the
X networking software. On MINIX systems, messages will be
X transported using either the UUCP networking software
X (serial lines) or the Amoeba RSMTP (Ethernet) software.
X
X Because it would be too difficult to program all sorts
X of networks, system names and the lot in the mailer
X software, a file exists which contains the Configuration
X parameters of Umail: the Config File. This is a plain
X ASCII text file, containing a mixture of comments, data
X and instructions.
X
XAUTHOR
X Steve R. Sampson (first draft of rmail program)
X Fred van Kempen, waltje@kyber.UUCP
X
XFILES
X /usr/spool/mail/user maildrop file
X /usr/spool/mail/user.lock lock for maildrop files
X /tmp/um* temporary file
X /usr/spool/uucp/* UUCP networking files
X /usr/spool/rsmtp/* SMTP networking files
X /usr/lib/uucp/umail.cf configuration file
X
XSEE ALSO
X wmail.doc
X
XBUGS
X The routing algorithm could be improved a lot.
X Also, the Config scanner should be more robust.
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X -- 2 --
X
X
+ END-OF-FILE umail.doc
chmod 'u=rw,g=r,o=r' 'umail.doc'
set `wc -c 'umail.doc'`
count=$1
case $count in
4082) :;;
*) echo 'Bad character count in ''umail.doc' >&2
echo 'Count should be 4082' >&2
esac
echo Extracting 'umail.h'
sed 's/^X//' > 'umail.h' << '+ END-OF-FILE ''umail.h'
X/*
X * UMAIL - MINIX Remote Domain-adressing Mail Router
X *
X * This version of RMAIL handles message-headers in a much
X * more "standard" way. It can handle bang-adresses, plus
X * the new-style Internet adressing (user@host.domain).
X * It is called by programs as "Mail" and "Uuxqt".
X *
X * D E F I N I T I O N S
X *
X * Author: F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl)
X */
X
X#ifdef MINIX
X# define VERSION "2.5/MINIX" /* 10/19/89 */
X# define CONFIG "/usr/lib/uucp/umail.cf"
X#endif
X
X#ifdef UNIX
X# define VERSION "2.5/UNIX" /* 10/19/89 */
X# define CONFIG "/usr/lib/uucp/umail.cf"
X#endif
X
X#ifndef TRUE
X# define FALSE 0
X# define TRUE 1
X#endif
X
Xtypedef struct __name {
X struct __name *next;
X char *name;
X} NAME;
X
Xtypedef struct __var {
X struct __var *next;
X char *name;
X char *value;
X} VAR;
X
Xtypedef struct __host {
X struct __host *next;
X char *name;
X int smart;
X char *command;
X char *opts;
X} HOST;
X
Xtypedef struct __routemap {
X struct __routemap *next;
X char *domain;
X char *host;
X char *route;
X} ROUTE;
X
Xtypedef struct {
X char user[256]; /* user name of adress */
X char host[256]; /* host name of adress */
X char domain[256]; /* domain name of adress */
X} BOX;
X
X#define NILNAME ((NAME *)NULL)
X#define NILVAR ((VAR *)NULL)
X#define NILHOST ((HOST *)NULL)
X#define NILROUTE ((ROUTE *)NULL)
X#define NILBOX ((BOX *)NULL)
X
X
X/* globals in ummain.c */
Xextern char *Version; /* UMAIL version ID */
Xextern int immediate, debug; /* commandline option flags */
Xextern int restrict; /* restricted (UUCP) use only */
Xextern int aremote; /* is adressee REMOTE or LOCAL ? */
Xextern char dfile[], infile[]; /* names of message temp-files */
Xextern char errmsg[]; /* global error message */
Xextern char mailsender[]; /* who sent the message? */
Xextern char mailaddr[]; /* final routed adress to use. */
Xextern char mailhost[]; /* which host to send to */
Xextern char mailcmd[]; /* command to use to send the mail */
Xextern char mailopts[]; /* which options the mailer uses */
Xextern NAME *namelist; /* list of my network names */
Xextern VAR *varlist; /* list of configuration variables */
Xextern HOST *hostlist; /* list of reacheable host names */
Xextern ROUTE *routemap; /* list of domain routes */
X
X/* configuration settings */
Xextern char *myname; /* my UUCP site name */
Xextern char *mydomain; /* my UUCP domain name */
Xextern char *myorg; /* Name of my organization */
Xextern int oldmailer; /* mailer uses old From-lines? */
Xextern int escape; /* routing ESCAPE enable */
X
X/* external routines */
Xextern char *xtime(/* time_t *salt */);
Xextern BOX *convert(/* char *adr */);
Xextern int route(/* BOX *box */);
Xextern int header(/* FILE *infp, FILE *outfp */);
Xextern char *strupr(/* char *s */);
Xextern char *strlwr(/* char *s */);
Xextern void add_name(/* char *name */);
Xextern void add_host(/* char *name, int smart, char *cmd, char *opts */);
Xextern void add_route(/* char *domain, char *host, char *route */);
Xextern void add_var(/* char *name, char *val */);
Xextern char *lookup(/* char *what */);
Xextern int boolean(/* char *ascii */);
Xextern HOST *gethost(/* char *host */);
Xextern ROUTE *getdomain(/* char *domain */);
Xextern char *mfgets(/* char *s, int n, FILE *iop */);
Xextern char *whoami(/* void */);
Xextern char *full_id(/* char *user */);
Xextern char *realname(/* char *who */);
Xextern char *maketime(/* long *salt */);
Xextern void fcopy(/* FILE *inf, FILE *outf */);
Xextern int scanner(/* char *fname */);
Xextern int KnowHost(/* char *name */);
Xextern int islocal(/* char *name */);
Xextern char *genname(/* int prefix, int grade, char *sysname */);
Xextern int send_local(/* char *user, char *data */);
Xextern int send_remote(/* char *rmtname, char *rmtuser, char *data */);
Xextern void errmail(/* char *str, int mgronly */);
Xextern int sendit(/* char *who, char *host, char *cmd, char *opts, char *data */);
+ END-OF-FILE umail.h
chmod 'u=rw,g=r,o=r' 'umail.h'
set `wc -c 'umail.h'`
count=$1
case $count in
3965) :;;
*) echo 'Bad character count in ''umail.h' >&2
echo 'Count should be 3965' >&2
esac
echo Extracting 'umconvert.c'
sed 's/^X//' > 'umconvert.c' << '+ END-OF-FILE ''umconvert.c'
X/*
X * UMAIL - MINIX Remote Domain-adressing Mail Router
X *
X * This version of RMAIL handles message-headers in a much
X * more "standard" way. It can handle bang-adresses, plus
X * the new-style Internet adressing (user@host.domain).
X * It is called by programs as "Mail" and "Uuxqt".
X *
X * A D R E S S C O N V E R S I O N M O D U L E
X *
X * Convert adresses into manageable chunks.
X *
X * We understand the following notations:
X *
X * 1. user@host.domain --> waltje@minixug.UUCP
X *
X * 2. host!user --> minixug!waltje
X *
X * 3. user --> waltje
X *
X * Return TRUE (1) if OK, or FALSE (0) if an error was encountered.
X *
X * Author: F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl)
X */
X#include <stdio.h>
X#include <alloc.h>
X#include <string.h>
X#include "umail.h"
X
X
X/*
X * Convert adress 'adr' into more manageable chunks.
X * Stuff the output into 'mailaddr' (the final user)
X * and 'mailcmd' (the mailer command to use).
X * Return NILBOX if an error ocurred.
X */
XBOX *convert(adr)
Xchar *adr;
X{
X static BOX box;
X char temp[1024];
X register char *bp, *sp, *cp;
X register ROUTE *rp;
X register HOST *hp;
X
X strcpy(mailaddr, adr);
X box.domain[0] = box.host[0] = '\0';
X box.user[0] = temp[0] = '\0';
X
X /*
X * Rule 1: Check for user@host.domain
X */
X sp = strrchr(mailaddr, '@');
X if (sp != NULL) {
X *sp++ = '\0';
X strcpy(box.user, mailaddr);
X strcpy(temp, sp);
X strlwr(temp); /* convert domain to lower case: RFC822 */
X
X /*
X * Rule 1A: Now check for "." in the domain part.
X * This indicates that a host name was given.
X */
X sp = strchr(temp, '.'); /* syntax host.domain ?? */
X if (sp == NULL) { /* no, onlky 'host' part */
X hp = gethost(temp); /* is this a local host? */
X if (hp != NILHOST) { /* yes! */
X strcpy(box.host, temp);
X box.domain[0] = '\0';
X return(&box);
X } else { /* no, must be a domain.... */
X strcpy(box.domain, temp);
X box.host[0] = '\0';
X return(&box);
X }
X } else { /* domain and host given! */
X *sp++ = '\0';
X strcpy(box.host, temp);
X strcpy(box.domain, sp);
X return(&box);
X }
X }
X
X /*
X * Rule 2: Check for host!user
X */
X sp = strchr(mailaddr, '!');
X if (sp != NULL) {
X *sp++ = '\0';
X strcpy(box.host, mailaddr);
X strcpy(box.user, sp);
X return(&box);
X }
X
X /*
X * Rule 3: Must be local user.
X */
X strcpy(box.user, mailaddr);
X box.host[0] = '\0';
X box.domain[0] = '\0';
X return(&box);
X}
X
+ END-OF-FILE umconvert.c
chmod 'u=rw,g=r,o=r' 'umconvert.c'
set `wc -c 'umconvert.c'`
count=$1
case $count in
2388) :;;
*) echo 'Bad character count in ''umconvert.c' >&2
echo 'Count should be 2388' >&2
esac
echo Extracting 'umroute.c'
sed 's/^X//' > 'umroute.c' << '+ END-OF-FILE ''umroute.c'
X/*
X * UMAIL - MINIX Remote Domain-adressing Mail Router
X *
X * This version of RMAIL handles message-headers in a much
X * more "standard" way. It can handle bang-adresses, plus
X * the new-style Internet adressing (user@host.domain).
X * It is called by programs as "Mail" and "Uuxqt".
X *
X * M A I L R O U T E R M O D U L E
X *
X * Some rules exist for routing to other machines.
X *
X * 1. Check for local system names.
X *
X * 2. If we have a domain, check it for validity.
X *
X * 3. If we have a hostname, check it for validity.
X *
X * 4. Local user: check existence.
X *
X * Examples are:
X *
X * user@host.domain@newdomain -
X * -> ast@cs.vu@nluug.nl
X * host!user@domain
X * --> cs.vu!ast@nluug.nl
X *
X * If we cannot find a matching domain or system name,
X * then we get stuck. Fortunately, we can define the
X * ESCAPE parameter, which allows us to send all mail
X * for unknown hosts or domains to a "default" domain.
X * This is the domain called "." in the tables.
X * If the ESCAPE parameter is FALSE, we cannot deliver
X * the message, so return it to the sender!
X *
X * Return TRUE (1) if OK, or FALSE (0) if an error was encountered.
X *
X * Author: F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl)
X */
X#include <stdio.h>
X#include <alloc.h>
X#include <pwd.h>
X#include <string.h>
X#include "umail.h"
X
X
X/*
X * Route the adress in BOX into a ready-to-run
X * UUCP adress.
X */
Xint route(b)
XBOX *b;
X{
X char temp[1024];
X register char *bp, *sp;
X register ROUTE *rp;
X register HOST *hp;
X struct passwd *pw;
X
X /*
X * Rule 1: check for local system names.
X * convert to LOCAL if possible.
X */
X if (b->domain[0] == '\0') strcpy(temp, b->host);
X else sprintf(temp, "%s.%s", b->host, b->domain);
X if (islocal(temp)) {
X b->host[0] = '\0';
X b->domain[0] = '\0';
X }
X
X /*
X * Rule 2: Do we have a domain?
X */
X if (b->domain[0] != '\0') { /* domain given? */
X if (b->host[0]) sprintf(temp, "%s.%s", b->host, b->domain);
X else strcpy(temp, b->domain);
X strcpy(b->host, temp);
X bp = temp;
X rp = NILROUTE;
X while (TRUE) { /* iterate on domain fragments */
X sp = bp;
X rp = getdomain(bp);
X if (rp != NILROUTE) { /* a matching domain! */
X strcpy(b->domain, bp);
X break;
X }
X bp = strchr(sp, '.');
X if (bp == NULL) break;
X else bp++;
X }
X
X /*
X * We now have checked the DOMAIN table for a matching domain.
X * If we failed to find a match, there is a problem.
X * If the mailer was defined with the ESCAPE parameter, we can
X * try to route it to the default (".") domain.
X * Otherwise, we cannot deliver the message...
X */
X
X /* check if we found a matching domain */
X if (rp == NILROUTE) { /* we did not. try to re-route it */
X if (escape == FALSE) {
X sprintf(errmsg, "%s ... domain unknown", b->domain);
X return(FALSE);
X }
X rp = getdomain("."); /* get default domain! */
X if (rp == NILROUTE) {
X sprintf(errmsg, "%s ... domain unknown", b->domain);
X strcat(errmsg, "\n\nESCAPE domain not found.");
X return(FALSE);
X }
X }
X
X /*
X * At this point we have all the information we
X * need to build an UUCP-adress.
X * We have a HOST as well.
X * Check if we can indeed reach that host.
X */
X hp = gethost(rp->host);
X if (hp == NILHOST) {
X sprintf(errmsg, "%s ... host unreacheble", rp->host);
X return(FALSE);
X }
X
X /* is the host smart enough to get "@"-adresses?? */
X if (hp->smart == TRUE) { /* yes, it is! */
X if (*(rp->route) == '@') {
X if (b->host[0] == '\0') sprintf(mailaddr,"%s@%s",
X b->user, b->domain);
X else sprintf(mailaddr, "%s@%s", b->user, b->host);
X } else {
X if (b->host[0] == '\0') sprintf(mailaddr,"%s!%s@%s",
X rp->route, b->user, b->domain);
X else sprintf(mailaddr, "%s!%s@%s.%s",
X rp->route, b->user, b->host, b->domain);
X }
X } else {
X if (b->host[0] == '\0') sprintf(mailaddr,"%s!%s",
X rp->route, b->user);
X else sprintf(mailaddr, "%s!%s!%s",
X rp->route, b->host, b->user);
X }
X strcpy(b->host, rp->host);
X
X /*
X * We now have a HOST and an ADRESS.
X */
X strcpy(mailcmd, hp->command);
X strcpy(mailopts, hp->opts);
X strcpy(mailhost, b->host);
X aremote = TRUE;
X return(TRUE);
X }
X
X /*
X * Rule 3: Do we have a host name ?
X */
X if (b->host[0] != '\0') { /* host name given? */
X b->domain[0] = '\0'; /* signal 'no routing' */
X hp = gethost(b->host);
X if (hp == NILHOST) {
X if (escape == FALSE) {
X sprintf(errmsg, "%s ... host unknown", b->host);
X return(FALSE);
X }
X rp = getdomain("."); /* get default domain! */
X if (rp == NILROUTE) {
X sprintf(errmsg, "%s ... host unknown", b->host);
X strcat(errmsg, "\n\nESCAPE domain not found.");
X return(FALSE);
X }
X
X /*
X * We now have a HOST as well.
X * Check if we can indeed reach that host.
X */
X strcpy(b->domain, rp->host);
X hp = gethost(rp->host);
X if (hp == NILHOST) {
X sprintf(errmsg, "%s ... host unreacheble", rp->host);
X return(FALSE);
X }
X }
X
X /*
X * USER contains the user-part
X * HOST contains the (old) host-part
X * DOMAIN now contains the new hostname
X */
X
X /* is the host smart enough to get "@"-adresses?? */
X if (b->domain[0] != '\0') { /* are we routing? */
X if (hp->smart == TRUE) sprintf(mailaddr, "%s@%s",
X b->user, b->host);
X else sprintf(mailaddr, "%s!%s", b->host, b->user);
X strcpy(b->host, b->domain);
X } else { /* no, ordinary case */
X strcpy(mailaddr, b->user);
X }
X
X strcpy(mailhost, b->host);
X strcpy(mailcmd, hp->command);
X strcpy(mailopts, hp->opts);
X aremote = TRUE;
X return(TRUE);
X }
X
X /*
X * Rule 4: Check for local user.
X */
X if ((pw = getpwnam(b->user)) == (struct passwd *)NULL) {
X sprintf(errmsg, "%s ... user unknown", b->user);
X return(FALSE);
X }
X hp = gethost(myname);
X strcpy(mailaddr, b->user);
X mailhost[0] = '\0';
X strcpy(mailcmd, hp->command);
X strcpy(mailopts, hp->opts);
X aremote = FALSE;
X return(TRUE);
X}
+ END-OF-FILE umroute.c
chmod 'u=rw,g=r,o=r' 'umroute.c'
set `wc -c 'umroute.c'`
count=$1
case $count in
5809) :;;
*) echo 'Bad character count in ''umroute.c' >&2
echo 'Count should be 5809' >&2
esac
echo Extracting 'umscanner.c'
sed 's/^X//' > 'umscanner.c' << '+ END-OF-FILE ''umscanner.c'
X/*
X * UMAIL - MINIX Remote Domain-adressing Mail Router
X *
X * This version of RMAIL handles message-headers in a much
X * more "standard" way. It can handle bang-adresses, plus
X * the new-style Internet adressing (user@host.domain).
X * It is called by programs as "Mail" and "Uuxqt".
X *
X * C O N F I G U R A T I O N F I L E S C A N N E R
X *
X * Author: F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl)
X */
X#include <stdio.h>
X
X
Xtypedef struct {
X char *name;
X int opcode;
X} WORD;
X
X
X/* operator opcodes */
X#define O_ASSIGN 1 /* ":=" */
X#define O_COMMA 2 /* "," */
X#define O_BEGIN 3 /* "BEGIN" */
X#define O_END 4 /* "END" */
X#define O_DATA 5 /* "DATA" */
X#define O_NAMES 6 /* "NAMES" */
X#define O_DOMAIN 7 /* "DOMAINS" */
X#define O_HOST 8 /* "HOST" */
X
X
X/* main scanner states */
X#define S_LOOK 1 /* looking for a keyword */
X#define S_BEGIN 2 /* got O_BEGIN */
X#define S_END 3 /* got O_END */
X
X/* block classes */
X#define SC_DATA 1 /* DATA (variable) class */
X#define SC_NAMES 2 /* NAMES (my domains) class */
X#define SC_DOMAIN 3 /* DOMAIN TABLE class */
X#define SC_HOST 4 /* HOSTS class */
X
X#define SS_LOOK 1 /* looking for keyword or variable name */
X#define SS_IDENT 2 /* looking for identifier */
X#define SS_ASSIGN 3 /* got varname, looking for O_COMMA */
X#define SS_COMMA 4 /* got varname, looking for O_ASSIGN */
X#define SS_VALUE 5 /* got O_ASSIGN, looking for value */
X#define SS_DOMAIN1 6 /* got domain, looking for hostname */
X#define SS_DOMAIN2 7 /* got boolean, looking for domain descr. */
X#define SS_HOST1 8 /* got host, looking for boolean */
X#define SS_HOST2 9 /* got host, looking for host mailer name */
X#define SS_HOST3 10 /* got host, looking for host mailer opts */
X
X
Xstatic FILE *infp; /* input file pointer */
Xstatic char scbuf[1024]; /* input line buffer */
Xstatic char *scptr = NULL; /* input line pointer */
Xstatic char *errptr = NULL; /* error pointer */
Xstatic char sctemp1[128]; /* current identifier */
Xstatic char sctemp2[128]; /* current identifier */
Xstatic int scbool; /* temp. boolean value */
Xstatic int lineno = 1; /* current line number */
Xstatic int sclass = SC_DATA; /* temporary state */
Xstatic int state = S_LOOK; /* state of scanner */
Xstatic int sstate = SS_LOOK; /* secondairy state */
Xstatic int tstate = SS_LOOK; /* triple state */
Xstatic WORD table[] = { /* language table */
X { ":=" , O_ASSIGN },
X { "," , O_COMMA },
X { "BEGIN" , O_BEGIN },
X { "END" , O_END },
X { "DATA" , O_DATA },
X { "NAMES" , O_NAMES },
X { "DOMAINS" , O_DOMAIN },
X { "HOSTS" , O_HOST },
X};
X
X
Xextern int debug;
X
X
X/*
X * Return next character of input file;
X * also do some bookkeeping for error-recovery.
X */
Xstatic int nextch(void)
X{
X register int ch;
X
X ch = fgetc(infp);
X if (ch == '\n') {
X lineno++;
X *scptr = '\0';
X scptr = scbuf;
X } else *scptr++ = ch;
X return(ch);
X}
X
X
X/*
X * Handle a syntax error.
X * Also, perform some error recovery.
X */
Xstatic void syntax(s)
Xchar *s;
X{
X register char *bp, *ep;
X register int ch;
X
X ep = errptr;
X do {
X ch = nextch(); /* read up to end of line */
X } while (ch!='\n' && ch!=EOF); /* and start over on next line */
X
X sstate = SS_LOOK; /* reset state machine #2 */
X
X fprintf(stderr, "%05.5d %s\n ", lineno, scbuf);
X bp = scbuf;
X ep--;
X while (bp < ep) {
X fprintf(stderr, " ");
X bp++;
X }
X fprintf(stderr, "^ %s\n", s);
X}
X
X
X/*
X * Check the text of a keyword.
X */
Xstatic int crunch(text)
Xchar *text;
X{
X register WORD *wp;
X
X wp = &table[0];
X while (wp->opcode != 0) {
X if (!strcmp(wp->name, text)) return(wp->opcode);
X wp++;
X }
X return(0);
X}
X
X
X/*
X * Decode a word, and perform some action if necessary.
X * This routine holds all the syntax grammar.
X * It is far from perfect, but it works...
X */
Xstatic void do_word(name)
Xchar *name;
X{
X int op; /* decoded keyword code */
X char *s = "expected END";
X
X op = crunch(name);
X if (sstate == SS_LOOK) switch(op) {
X case O_DATA:
X if (state==S_LOOK || state==S_END) sclass = SC_DATA;
X else syntax(s);
X break;
X case O_NAMES:
X if (state==S_LOOK || state==S_END) sclass = SC_NAMES;
X else syntax(s);
X break;
X case O_DOMAIN:
X if (state==S_LOOK || state==S_END) sclass = SC_DOMAIN;
X else syntax(s);
X break;
X case O_HOST:
X if (state==S_LOOK || state==S_END) sclass = SC_HOST;
X else syntax(s);
X break;
X case O_BEGIN:
X switch(sclass) {
X case SC_DATA:
X case SC_DOMAIN:
X case SC_HOST:
X case SC_NAMES:
X sstate = SS_LOOK;
X state = S_BEGIN;
X break;
X default:
X syntax("expected class prefix");
X break;
X }
X break;
X case O_END:
X if (state == S_BEGIN) {
X state = S_LOOK;
X sclass = 0;
X } else syntax("expected BEGIN");
X break;
X default:
X sstate = SS_IDENT;
X break;
X }
X switch(sstate) {
X case SS_LOOK: /* propagated from the above switch() */
X break;
X case SS_IDENT: /* looking for identifier */
X switch(sclass) {
X case SC_DATA:
X case SC_HOST:
X case SC_DOMAIN:
X strcpy(sctemp1, name);
X sstate = SS_ASSIGN;
X break;
X case SC_NAMES:
X add_name(name);
X sstate = SS_LOOK;
X break;
X default:
X syntax("expected BEGIN or CLASS");
X }
X break;
X case SS_ASSIGN: /* looking for O_ASSIGN */
X op = crunch(name);
X if (op == O_ASSIGN) switch(sclass) { /* found O_ASSIGN */
X case SC_DATA:
X sstate = SS_VALUE;
X break;
X case SC_DOMAIN:
X sstate = SS_DOMAIN1;
X break;
X case SC_HOST:
X sstate = SS_HOST1;
X break;
X default:
X break;
X } else syntax("expected ASSIGN");
X break;
X case SS_COMMA: /* field separator */
X op = crunch(name);
X if (op == O_COMMA) switch(sclass) {
X case SC_DOMAIN:
X sstate = SS_DOMAIN2;
X break;
X case SC_HOST:
X switch(tstate) {
X case SS_HOST1:
X sstate = SS_HOST2;
X break;
X case SS_HOST2:
X sstate = SS_HOST3;
X break;
X default:
X syntax("no comma here");
X break;
X }
X break;
X default:
X syntax("no comma here");
X break;
X } else syntax("expected COMMA");
X break;
X case SS_VALUE: /* looking for value */
X add_var(sctemp1, name);
X sstate = SS_LOOK;
X break;
X case SS_DOMAIN1: /* looking for route hostname */
X strcpy(sctemp2, name);
X sstate = SS_COMMA;
X break;
X case SS_DOMAIN2: /* looking for host route */
X add_route(sctemp1, sctemp2, name);
X sstate = SS_LOOK;
X break;
X case SS_HOST1: /* looking for host 'smart' boolean */
X scbool = boolean(name);
X sstate = SS_COMMA;
X tstate = SS_HOST1;
X break;
X case SS_HOST2: /* looking for host mailer name */
X strcpy(sctemp2, name); /* mailer name */
X sstate = SS_COMMA; /* look for mailer opts */
X tstate = SS_HOST2;
X break;
X case SS_HOST3: /* looking for host mailer opts */
X add_host(sctemp1, scbool, sctemp2, name);
X sstate = SS_LOOK;
X break;
X default: /* this can't be for real! */
X syntax("Huh? You must be joking!");
X break;
X }
X}
X
X
X/*
X * This is the Configuration File Scanner.
X * It has *some* level of intelligence, but is must
X * be improved a lot.
X */
Xint scanner(fname)
Xchar *fname;
X{
X char wordbuf[512];
X register char *bp = wordbuf;
X register int ch;
X register int quote = 0;
X register int stopped = 0;
X
X infp = fopen(fname, "r");
X if (infp == (FILE *)NULL) return(-1);
X
X scptr = scbuf;
X ch = nextch();
X do {
X switch(ch) {
X case '#': /* comment, skip rest of line */
X do {
X ch = nextch();
X } while (ch != '\n');
X break;
X case ' ': /* SPACE */
X case '\t':
X if (quote == 0) {
X errptr = scptr;
X do { /* skip rest of leading space */
X ch = nextch();
X } while (ch==' ' || ch=='\t');
X *bp = '\0';
X if (bp != wordbuf) {
X do_word(wordbuf);
X bp = wordbuf;
X }
X } else {
X *bp++ = ch;
X ch = nextch();
X }
X break;
X case EOF: /* EOF, done! */
X stopped = 1;
X case '\n': /* end-of-word marker, handle word */
X *bp = '\0';
X if (wordbuf[0]) {
X do_word(wordbuf);
X bp = wordbuf;
X }
X if (ch != EOF) ch = nextch();
X break;
X case '"': /* quote, set/reset quoting flag */
X quote = 1 - quote;
X ch = nextch();
X break;
X default: /* anything else: text */
X *bp++ = ch;
X ch = nextch();
X break;
X }
X } while (!stopped);
X
X fclose(infp);
X
X return(0);
X}
+ END-OF-FILE umscanner.c
chmod 'u=rw,g=r,o=r' 'umscanner.c'
set `wc -c 'umscanner.c'`
count=$1
case $count in
9752) :;;
*) echo 'Bad character count in ''umscanner.c' >&2
echo 'Count should be 9752' >&2
esac
echo Extracting 'umsend.c'
sed 's/^X//' > 'umsend.c' << '+ END-OF-FILE ''umsend.c'
X/*
X * UMAIL - MINIX Remote Domain-adressing Mail Router
X *
X * This version of RMAIL handles message-headers in a much
X * more "standard" way. It can handle bang-adresses, plus
X * the new-style Internet adressing (user@host.domain).
X * It is called by programs as "Mail" and "Uuxqt".
X *
X * M A I L T R A N S P O R T M O D U L E
X *
X * Author: F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl)
X */
X#include <stdio.h>
X#include <sys/types.h>
X#include <dirent.h>
X#include <errno.h>
X#include <string.h>
X#include <time.h>
X#include <uucp.h>
X#include "umail.h"
X
X
X/*
X * Check the host machine name.
X *
X * returns FALSE if not found, else TRUE
X */
Xint KnowHost(name)
Xchar *name;
X{
X register HOST *hp;
X
X hp = gethost(name);
X return((hp==NILHOST) ? FALSE : TRUE);
X}
X
X
X/*
X * Check if this is one of our local names.
X * Return 1 if TRUE, or 0 if FALSE.
X */
Xint islocal(name)
Xchar *name;
X{
X register NAME *np;
X
X np = namelist;
X while (np != NILNAME) {
X if (!strcmp(np->name, name)) return(TRUE);
X np = np->next;
X }
X return(FALSE);
X}
X
X
X/*
X * Creates a unique UUCP file name, and returns a pointer
X * to it. The filename is a combination of prefix, grade, system name
X * and a sequential number taken from SPOOLSEQ.
X */
Xchar *genname(prefix, grade, sysname)
Xint prefix, grade;
Xchar *sysname;
X{
X static char _gen_buf[128];
X int i = 0;
X char seqline[10];
X char *seqname = SPOOLSEQ; /* to save some string space */
X char *lseqname = LSPOOLSEQ; /* to save some string space */
X FILE *spoolseq;
X
X if (access(seqname, 0) != 0) close(creat(seqname, 0600));
X
X while(link(seqname, lseqname) != 0) {
X sleep(5);
X if (++i > 5) return(NULL);
X }
X
X spoolseq = fopen(seqname, "r");
X fgets(seqline, sizeof(seqline), spoolseq);
X fclose(spoolseq);
X unlink(lseqname);
X
X i = (atoi(seqline) + 1);
X
X if ((spoolseq = fopen(seqname, "w")) == (FILE *)NULL) return(NULL);
X fprintf(spoolseq, "%d\n", i);
X fclose(spoolseq);
X
X if (grade == 0) sprintf(_gen_buf, "%c.%.7s%04.4x", prefix, sysname, i);
X else sprintf(_gen_buf, "%c.%.7s%c%04.4x", prefix, sysname, grade, i);
X
X return(_gen_buf);
X}
X
X
X/*
X * Deliver this message to a local user.
X * We do this by calling "LMAIL" (which is actually
X * a link to "Mail"; the Local Mail Agent.
X */
Xint send_local(user, data)
Xchar *user;
Xchar *data;
X{
X struct passwd *pw;
X char tmpbuf[128];
X
X /* See if destination user name exists on this machine */
X pw = (struct passwd *) getpwnam(user);
X if (pw == (struct passwd *)NULL) {
X sprintf(tmpbuf, "%s ... unknown user at %s", user, myname);
X errmail(tmpbuf, FALSE);
X }
X
X#ifdef WMAILER /* faster than redirecting! */
X sprintf(tmpbuf, "exec %s -i%s %s", LMAIL, data, user);
X#else
X sprintf(tmpbuf, "exec %s <%s %s", LMAIL, data, user);
X#endif WMAILER
X
X return(system(tmpbuf));
X}
X
X
X/*
X * Deliver this message to a remote user.
X * We do this by creating the spoolfiles needed by UUCICO.
X * Then we call that program daemon to do the real work.
X */
Xint send_remote(rmtname, rmtuser, data)
Xchar *rmtname;
Xchar *rmtuser;
Xchar *data;
X{
X char tmpbuf[128];
X char Bfile[128], Cfile[128], Dfile[128], Xfile[128];
X FILE *fcfile, *fbfile, *fdfile, *fp;
X
X if (KnowHost(rmtname) == FALSE) {
X sprintf(tmpbuf, "%s ... unknown host machine", rmtname);
X errmail(tmpbuf, FALSE);
X }
X
X /* make the spool files for uucico */
X strcpy(Bfile, genname('B', 0, rmtname));
X strcpy(Cfile, genname('C', 'N', rmtname));
X strcpy(Dfile, genname('D', 0, myname));
X strcpy(Xfile, genname('X', 'N', rmtname));
X
X /* Copy the temp-file to the UUCP data file (D.???) */
X if ((fdfile = fopen(Dfile, "w")) == (FILE *)NULL) {
X perror("rmail 4");
X exit(1);
X } else {
X fp = fopen(data, "r"); /* open temp-file */
X fcopy(fp, fdfile);
X fclose(fdfile);
X fclose(fp);
X }
X
X if ((fbfile = fopen(Bfile, "w")) == (FILE *)NULL) {
X perror("rmail 4");
X exit(1);
X } else {
X fprintf(fbfile, "U %s %s\nF %s\nI %s\nC rmail %s\n",
X UUCPUSER, myname, Dfile, Dfile, rmtuser);
X fclose(fbfile);
X }
X
X if ((fcfile = fopen(Cfile, "w")) == (FILE *)NULL) {
X perror("rmail 5");
X exit(1);
X } else {
X fprintf(fcfile,"S %s %s %s - %s 0666\nS %s %s %s - %s 0666\n",
X Dfile, Dfile, UUCPUSER, Dfile, Bfile, Xfile, UUCPUSER, Bfile);
X fclose(fcfile);
X }
X
X /* RMAIL is setUID root... UUCP cannot read these files! */
X chown(Bfile, UUCPUID, UUCPGID);
X chown(Cfile, UUCPUID, UUCPGID);
X chown(Dfile, UUCPUID, UUCPGID);
X chown(Xfile, UUCPUID, UUCPGID);
X
X if (immediate == TRUE) { /* call uucico now! */
X strcpy(tmpbuf, UUCICO);
X sprintf(tmpbuf, "exec %s -s%s -x1 >/dev/null &", UUCICO, rmtname);
X system(tmpbuf);
X }
X
X return(FALSE);
X}
X
X
X/*
X * Perform the mail-transport.
X * We do this by calling the appropriate mailer.
X * If the name of the mailer is "$$" then we can use
X * this program to deliver. This saves a lot of memory.
X */
Xint sendit(who, host, cmd, opts, data)
Xchar *who; /* who is the adressee? */
Xchar *host; /* on which machine? */
Xchar *cmd; /* what command should we use? */
Xchar *opts; /* which options? */
Xchar *data; /* name of data (message) file */
X{
X char cmdline[512];
X char tmpbuff[512];
X
X chdir(SPOOLDIR); /* Change to UUCP directory */
X
X if (!strcmp(cmd, "$$")) { /* run our own mail routines */
X if (*host == '\0') send_local(who, data);
X else send_remote(host, who, data);
X } else {
X sprintf(tmpbuff, "exec %s %s ", cmd, opts);
X sprintf(cmdline, tmpbuff, data); /* create commandline */
X strcat(cmdline, who); /* add user adress */
X system(cmdline); /* execute command (mailer) */
X }
X}
X
X
X/*
X * Send mail to system manager upon errors
X *
X * Mail is contained in a file referenced
X * by Global variable 'dfile'
X */
Xvoid errmail(str, mgronly)
Xchar *str;
Xint mgronly;
X{
X FILE *fp, *tp;
X long now;
X char fname[32];
X char tmp[128];
X
X strcpy(fname, "/tmp/umeXXXXXX");
X mktemp(fname);
X
X tp = fopen(fname, "w");
X fp = fopen(dfile, "r");
X
X time(&now);
X
X /* create header of the report-message */
X fprintf(tp, "From %s %s\n", ERRUSER, xtime(&now));
X if (mailsender != NULL) fprintf(tp, "To: %s\n", mailsender);
X fprintf(tp, "Subject: Returned mail\n\n");
X
X /* create an error transcript */
X fprintf(tp, " ---- Transcript of session follows ----\n\n");
X fprintf(tp, "%s\n", str);
X fprintf(tp, "\n ---- Unsent message follows ----\n");
X
X /* copy the message */
X while (mfgets(tmp, sizeof(tmp), fp) != (char *)NULL)
X fprintf(tp, "> %s\n", tmp);
X
X fclose(tp); /* flush and close message file */
X fclose(fp); /* flush and close orig. file */
X
X /* Return mail to system manager (and sender if mgronly == FALSE) */
X if (mgronly == FALSE) sendit(mailsender, "", RMAIL, " <%s", fname);
X
X /* send mail to UUCP administrator */
X sendit(ERRUSER, "", "$$", "", fname);
X
X unlink(fname); /* remove data files */
X unlink(dfile);
X
X exit(1); /* and exit! */
X}
+ END-OF-FILE umsend.c
chmod 'u=rw,g=r,o=r' 'umsend.c'
set `wc -c 'umsend.c'`
count=$1
case $count in
6827) :;;
*) echo 'Bad character count in ''umsend.c' >&2
echo 'Count should be 6827' >&2
esac
echo Extracting 'umtime.c'
sed 's/^X//' > 'umtime.c' << '+ END-OF-FILE ''umtime.c'
X/*
X * XTIME - Create ASCII string of the given time.
X * This file contains a modified version
X * of the ctime(3) function from the MINIX
X * C library. The format of the string is:
X *
X * Sat, Oct 14 89 20:26:00\0
X *
X */
X#include <time.h>
X
X
Xstatic int days_per_month[] = {
X 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
X};
Xstatic char *months[] = {
X "Jan", "Feb", "Mar", "Apr", "May", "Jun",
X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
X};
Xstatic char *days[] = {
X "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
X};
X
X#define MIN 60L /* # seconds in a minute */
X#define HOUR (60 * MIN) /* # seconds in an hour */
X#define DAY (24 * HOUR) /* # seconds in a day */
X#define YEAR (365 * DAY) /* # seconds in a year */
X
X
Xchar *xtime(pt)
Xlong *pt;
X{
X static struct tm tm;
X static char xtmbuf[30];
X
X register long t = *pt;
X long year;
X
X tm.tm_year = 0;
X tm.tm_mon = 0;
X tm.tm_mday = 1;
X tm.tm_hour = 0;
X tm.tm_min = 0;
X tm.tm_sec = 0;
X
X /* t is elapsed time in seconds since Jan 1, 1970. */
X tm.tm_wday = (int) (t/DAY + 4L) % 7; /* Jan 1, 1970 is 4th wday */
X while (t >= (year=((tm.tm_year%4)==2) ? YEAR+DAY : YEAR)) {
X tm.tm_year += 1;
X t -= year;
X }
X tm.tm_year += 1970;
X
X /* t is now the offset into the current year, in seconds. */
X tm.tm_yday = (t/DAY); /* day # of the year, Jan 1 = 0 */
X
X days_per_month[1] = 28;
X if ((tm.tm_year % 4) == 0) /* check for leap year */
X days_per_month[1]++;
X
X /* Compute month. */
X while (t >= (days_per_month[tm.tm_mon] * DAY))
X t -= days_per_month[tm.tm_mon++] * DAY;
X
X /* Month established, now compute day of the month */
X while (t >= DAY) {
X t -= DAY;
X tm.tm_mday++;
X }
X
X /* Day established, now do hour. */
X while (t >= HOUR) {
X t -= HOUR;
X tm.tm_hour++;
X }
X
X /* Hour established, now do minute. */
X while (t >= MIN) {
X t -= MIN;
X tm.tm_min++;
X }
X
X /* Residual time is # seconds. */
X tm.tm_sec = (int) t;
X
X /* Generate output in ASCII in _buf_. */
X sprintf(xtmbuf, "%s, %2.2d %s %2.2d %02d:%02d:%02d",
X days[tm.tm_wday], tm.tm_mday, months[tm.tm_mon],
X tm.tm_year - 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
X return(xtmbuf);
X}
+ END-OF-FILE umtime.c
chmod 'u=rw,g=r,o=r' 'umtime.c'
set `wc -c 'umtime.c'`
count=$1
case $count in
2113) :;;
*) echo 'Bad character count in ''umtime.c' >&2
echo 'Count should be 2113' >&2
esac
echo Extracting 'uucp.h'
sed 's/^X//' > 'uucp.h' << '+ END-OF-FILE ''uucp.h'
X/*
X * UUCP.H- DCP: A UUCP clone.
X * Definitions for the UUCP package
X *
X * Copyright Richard H. Lamb 1985,1986,1987
X * Copyright S. R. Sampson, August 1989
X * Copyright F. N. G. van Kempen Jul-Oct '89
X */
X
X#ifndef TRUE
X# define FALSE 0
X# define TRUE 1
X#endif
X
X#define LSYS "/usr/lib/uucp/L.sys"
X#define LDEVICE "/usr/lib/uucp/L-devices"
X#define UUCICO "/usr/lib/uucp/uucico"
X#define UUXQT "/usr/lib/uucp/uuxqt"
X#define RMAIL "rmail" /* Remote Mailer */
X#define SMAIL "smail" /* Internet Mailer */
X#define LMAIL "lmail" /* Local Mailer */
X#define SYSLOG "/usr/lib/uucp/Log/uucico.log"
X#define XQTLOG "/usr/lib/uucp/Log/uuxqt.log"
X#define PUBDIR "/usr/spool/uucppublic"
X#define SPOOLDIR "/usr/spool/uucp"
X#define SPOOLSEQ "/usr/lib/uucp/SPOOLSEQ"
X#define LSPOOLSEQ "/usr/lib/uucp/SPOOLSEQ.LCK"
X#define LOCKFILE "/usr/spool/locks/LCK..%s" /* terminal LOCKfile */
X#define GLOCKFILE "/usr/spool/locks/GLOCK..%s" /* terminal LOCKfile */
X#define NODENAME "/etc/uucpname"
X#define CALLFILE "C.%s"
X#define XQTFILE "X.%s"
X#define MAILFILE "B.%s"
X
X#define UUCPUSER "uucp"
X#define ERRUSER "postmaster"
X
X#define UUCPUID 40 /* RMAIL needs these */
X#define UUCPGID 40
X#define POSTUID 41 /* RMAIL needs these */
X#define POSTGID 40
X
X#define SITENAMELEN 32
X#define PATHLEN 256
X
X#define MSGTIME 20
X#define MAXPACK 256
X
X/* L.sys field defines */
X#define FLD_REMOTE 0 /* remote system name */
X#define FLD_CCTIME 1 /* legal call times */
X#define FLD_DEVICE 2 /* device, or ACU for modem */
X#define FLD_SPEED 3 /* bit rate */
X#define FLD_PHONE 4 /* phone number */
X#define FLD_EXPECT 5 /* first login "expect" field */
X#define FLD_SEND 6 /* first login "send" field */
X
+ END-OF-FILE uucp.h
chmod 'u=rw,g=r,o=r' 'uucp.h'
set `wc -c 'uucp.h'`
count=$1
case $count in
1882) :;;
*) echo 'Bad character count in ''uucp.h' >&2
echo 'Count should be 1882' >&2
esac
exit 0