chip@ateng.UUCP (Chip Salzenberg) (12/01/87)
This posting is a sharchive of my modifications to smail 2.5 for use under
SCO Xenix System V. I've only run it on Xenix/286 v2.2.0, but I can't
imagine that my code isn't portable. ;-)
DISCLAIMER AHEAD - DANGER WILL ROBINSON
>> Sorry, I'm not responsible for lost mail. Your mileage may vary.
END OF DISCLAIMER
What to do:
1. Unpack the sharchive.
2. Integrate the resulting files with the standard smail files.
This may be as simple as `mv * /usr/src/smail', although it
would be good to check the defs.h file for correctness
before proceeding.
3. Compile smail and execm with the command `make'.
4. As root, run `./install_smail'.
Note that as shipped, this modification to smail gives you two (count 'em, two)
alias files. Smail uses /usr/lib/mail/saliases; you can use RFC822 addresses
here. Execmail uses /usr/lib/mail/aliases; you can use pipe aliases here.
(You know, "rnews: |/usr/lib/news/uurec" and the like.)
To use RFC822 addresses with Xenix `mail', add the line "set execmail" to the
/usr/lib/mail/mailrc file.
"It is forbidden to take the Bastille"
-- Sign in pre-revolutionary France
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the "#! /bin/sh" line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# Makefile
# install_smail
# execm.c
# defs.h
# deliver.c
# This archive created: Tue Dec 1 16:04:26 1987
export PATH; PATH=/bin:$PATH
:
echo 'shar: extracting "Makefile" (1246 characters) '
if test -f 'Makefile'
then
echo 'shar: will not overwrite existing file "Makefile" '
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X# Makefile for smail
X# @(#)Makefile 2.5 (smail) 9/15/87
X#
X# Modified for SCO Xenix by Chip Salzenberg (chip@ateng.UUCP).
X# Released to Usenet on 01 Dec 1987.
X#
X# With the addition of the `all' pseudo-target, this makefile now makes
X# both smail and execm by default.
X#
X# Use the `install_smail' script to install the resulting binaries.
X
XCFLAGS = -O
XLDFLAGS = -i
XSHELL = /bin/sh
X
X#
X# System V Release 2.0 sites can use -lmalloc for a faster malloc
X#
X#LIBS = -lmalloc
X
XOBJECTS = main.o map.o resolve.o deliver.o misc.o alias.o pw.o headers.o getpath.o str.o getopt.o
X
Xall: smail execm
X
Xsmail: $(OBJECTS)
X $(CC) $(LDFLAGS) -F 4000 $(OBJECTS) -o smail $(LIBS)
X
X$(OBJECTS): defs.h
X $(CC) $(CFLAGS) -c $<
X
Xexecm: execm.c
X $(CC) $(CFLAGS) execm.c -o execm
X
Xsvbinmail: svbinmail.c defs.h
X $(CC) $(LDFLAGS) svbinmail.c -o svbinmail
X
Xlcasep: lcasep.c
X $(CC) $(LDFLAGS) lcasep.c -o lcasep
X
Xpathproc: pathproc.sh
X $(COPY) pathproc.sh pathproc
X chmod 755 pathproc
X
Xmkfnames: mkfnames.sh
X $(COPY) mkfnames.sh mkfnames
X chmod 755 mkfnames
X
Xnptx: nptx.o pw.o str.o
X $(CC) $(CFLAGS) nptx.o pw.o str.o -o nptx $(LIBS)
X
Xclean:
X rm -f *.o *.ln a.out core
X
Xclobber: clean
X rm -f smail rmail lcasep pathproc mkfnames svbinmail nptx
SHAR_EOF
if test 1246 -ne `wc -c < 'Makefile'`
then
echo 'shar: error transmitting "Makefile" (should have been 1246 characters) '
fi
chmod 664 'Makefile'
fi # end of overwriting check
:
echo 'shar: extracting "install_smail" (1137 characters) '
if test -f 'install_smail'
then
echo 'shar: will not overwrite existing file "install_smail" '
else
sed 's/^X//' << \SHAR_EOF > 'install_smail'
X: install_smail
X# Shell script to install smail in a Xenix System V system.
X#
X# Written by Chip Salzenberg (chip@ateng.UUCP).
X# Released to Usenet on 01 Dec 1987.
X#
X# Note that this script renames the standard Xenix rmail and execmail
X# programs to rmail.x and execmail.x respectively. If those `.x' files
X# already exist, then no renaming takes place, so you can run this script
X# more than once without losing those renamed programs.
X#
X# BTW, be sure to test everything thoroughly; a broken mail system is
X# sure to upset any users on your system.
X
XCOPY="copy -m"
XSMAIL="/usr/bin/smail"
XRMAIL="/usr/bin/rmail"
XEXECM="/usr/lib/mail/execmail"
X
Xfor f in smail execm
Xdo
X if [ ! -x $f ]; then
X echo "You need to compile $f first."
X exit 1
X fi
Xdone
X
Xecho "Installing current smail -- you have 5 seconds to abort."
Xsleep 5
X
Xif [ ! -f $RMAIL.x ]; then
X mv $RMAIL $RMAIL.x
Xfi
Xrm -f $RMAIL
Xif [ ! -f $EXECM.x ]; then
X mv $EXECM $EXECM.x
Xfi
Xrm -f $EXECM
X
X$COPY execm $EXECM
Xchown bin $EXECM
Xchgrp bin $EXECM
Xchmod 755 $EXECM
X
Xrm -f $SMAIL $RMAIL
X$COPY smail $SMAIL
Xchown bin $SMAIL
Xchgrp bin $SMAIL
Xchmod 755 $SMAIL
Xln $SMAIL $RMAIL
SHAR_EOF
if test 1137 -ne `wc -c < 'install_smail'`
then
echo 'shar: error transmitting "install_smail" (should have been 1137 characters) '
fi
chmod 775 'install_smail'
fi # end of overwriting check
:
echo 'shar: extracting "execm.c" (747 characters) '
if test -f 'execm.c'
then
echo 'shar: will not overwrite existing file "execm.c" '
else
sed 's/^X//' << \SHAR_EOF > 'execm.c'
X/*
X * execm.c
X *
X * This program is a substitute for Xenix's /usr/lib/mail/execmail.
X *
X * Written by Chip Salzenberg (chip@ateng.UUCP).
X * Released to Usenet on 01 Dec 1987.
X *
X * Do what you want with it; I'm not responsible for lost mail,
X * but I don't expect that this little program will lose anything.
X */
X
X#include <stdio.h>
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X char *progname = argv[0];
X
X /*
X * Drop the execmail options.
X */
X while (argv[1][0] == '-')
X {
X switch (argv[1][1])
X {
X case 'f':
X case 'h':
X argv += 2;
X break;
X default:
X ++argv;
X break;
X }
X }
X
X argv[0] = progname;
X execv("/usr/bin/smail", argv);
X execv("/bin/smail", argv);
X
X fprintf(stderr, "%s: can't execute smail!\n", progname);
X exit(1);
X}
SHAR_EOF
if test 747 -ne `wc -c < 'execm.c'`
then
echo 'shar: error transmitting "execm.c" (should have been 747 characters) '
fi
chmod 664 'execm.c'
fi # end of overwriting check
:
echo 'shar: extracting "defs.h" (11012 characters) '
if test -f 'defs.h'
then
echo 'shar: will not overwrite existing file "defs.h" '
else
sed 's/^X//' << \SHAR_EOF > 'defs.h'
X/*
X**
X** Defs.h: header file for rmail/smail.
X**
X** Configuration options for rmail/smail.
X** default configuration is:
X** full domain name is 'hostname.uucp' (get registered!)
X** path file is /usr/lib/uucp/paths.
X** no log, no record, use sendmail.
X**
X** You can change these in the next few blocks.
X**
X*/
X
X/*
X** @(#)defs.h 2.5 (smail) 9/15/87
X*/
X
X/*
X** Modified for SCO Xenix by Chip Salzenberg (chip@ateng.UUCP).
X** Released to Usenet on 01 Dec 1987.
X**
X** SCO's compiler automatically defines M_XENIX; we use it here.
X**
X** Note that we define EXECMAIL here; Xenix's execmail is almost,
X** but not quite, entirely unlike sendmail. :-) Thus it is not
X** quite useful to define SENDMAIL as "execmail".
X*/
X
X#ifndef VERSION
X#define VERSION "smail2.5"
X#endif
X
X/*#define BSD /* if system is a Berkeley system */
X/*#define SENDMAIL "/usr/lib/sendmail" /* if system has Berkeley sendmail */
X
X#ifdef BSD
X#define GETHOSTNAME /* use gethostname() */
X#else
X#define UNAME /* use uname() */
X#endif
X
X/* if defined, HOSTNAME overrides UNAME and GETHOSTNAME */
X/*#define HOSTNAME "host" /* literal name */
X
X/*#define HOSTDOMAIN "host.dom" /* overrides default HOSTNAME.MYDOM */
X
X/*
X * .UUCP here is just for testing, GET REGISTERED in COM, EDU, etc.
X * See INFO.REGISTRY for details.
X */
X
X#define MYDOM ".UUCP" /* literal domain suffix */
X
X/*
X * WARNING: DOMGATE is only for qualified gateways - use caution.
X * If you don't fully understand it - don't use it!
X * If you are not completely sure you need it - don't use it!
X * If you are not prepared to handle all addresses to MYDOM - don't use it!
X *
X * if defined, DOMGATE (DOMain GATEway) will cause addresses of the form
X *
X * user@MYDOM or MYDOM!user
X *
X * (with and without the leading '.' on MYDOM)
X * to be seen treated simply 'user' - a purely local address.
X * Then, it is left to the aliasing code to map it back to a
X * non-local address if necessary.
X */
X
X/*#define DOMGATE /* Act as Domain Gateway */
X
X/*
X * HIDDENHOSTS allows hosts that serve as domain gateways to hide
X * the subdomains beneath them. Mail that originates at any of
X * the hosts in the subdomain will appear to come from the gateway host.
X * Hence, mail from
X *
X * anything.hostdomain!user
X *
X * will appear to come from
X *
X * hostdomain!user
X *
X * A consequence is that return mail to hostdomain!user would need to
X * be forwarded to the proper subdomain via aliases or other forwarding
X * facilities.
X *
X * If you're using sendmail, then if defined here,
X * it should be used in ruleset 4 of the sendmail.cf, too.
X */
X
X/*#define HIDDENHOSTS /* hide subdomains of hostdomain */
X
X/*
X * Mail that would otherwise be undeliverable will be passed to the
X * aliased SMARTHOST for potential delivery.
X *
X * Be sure that the host you specify in your pathalias input knows that you're
X * using it as a relay, or you might upset somebody when they find out some
X * other way. If you're using 'foovax' as your relay, and below you have
X * #define SMARTHOST "smart-host", then the pathalias alias would be:
X *
X * smart-host = foovax
X */
X
X#define SMARTHOST "smart-host" /* pathalias alias for relay host */
X
X/*
X** ALIAS and CASEALIAS are used only if SENDMAIL is NOT defined.
X** Sites using sendmail have to let sendmail do the aliasing.
X** LOWERLOGNAME maps all local login names into lower case. This
X** helps sites who have only upper case send mail to mixed case sites.
X*/
X
X /* Location of mail aliases */
X#ifdef M_XENIX
X#define ALIAS "/usr/lib/mail/saliases"
X#else
X#define ALIAS "/usr/lib/aliases"
X#endif
X/*#define CASEALIAS /* make aliases case sensitive */
X/*#define LOWERLOGNAME /* map local logins to lower case */
X
X/*
X * defining FULLNAME means that Full Name resolution
X * will be attempted when necessary.
X *
X * the Full Name information will be taken from a
X * list of {Full Name, address} pairs.
X * The names in the list must be sorted
X * without regard to upper/lower case.
X *
X * defining DOT_REQD says that the user name must contain a '.' for
X * the Full Name search to be done.
X *
X * All full name searches are case insensitive.
X *
X */
X
X /* list of Full Name, address pairs */
X#ifdef M_XENIX
X#define FULLNAME "/usr/lib/mail/fullnames"
X#else
X#define FULLNAME "/usr/lib/fullnames"
X#endif
X
X/*#define DOT_REQD /* Must be George.P.Burdell@gatech.EDU
X ** not just Burdell@gatech.EDU
X */
X
X/*
X** PATHS is name of pathalias file. This is mandatory.
X** Define LOG if you want a log of mail. This can be handy for
X** debugging and traffic analysis.
X** Define RECORD for a copy of all mail. This uses much time and
X** space and is only used for extreme debugging cases.
X*/
X
X#ifndef PATHS
X#define PATHS "/usr/lib/uucp/paths" /* location of the path database */
X#endif
X
X#define LOG "/usr/spool/uucp/mail.log" /* log of uucp mail */
X/*#define RECORD "/tmp/mail.log" /* record of uucp mail */
X
X/*
X** Mailer options:
X** RMAIL is the command to invoke rmail on machine sys.
X** RARG is how to insulate metacharacters from RMAIL.
X** LMAIL is the command to invoke the local mail transfer agent.
X** LARG is how to insulate metacharacters from LMAIL.
X** RLARG is LARG with host! on the front - to pass a uux addr to sendmail.
X** SENDMAIL selects one of two sets of defines below for either
X** using sendmail or /bin/lmail.
X*/
X
X#ifndef UUX
X#define UUX "/usr/bin/uux" /* location of uux command */
X#endif
X
X#ifndef SMAIL
X#define SMAIL "/usr/bin/smail" /* location of smail command */
X#endif
X
X/*
X** command used to retry failed mail, flag is used to set the routing level.
X*/
X#define VFLAG ((debug == VERBOSE)?"-v":"")
X#define RETRY(flag) "%s %s %s -f %s ", SMAIL, VFLAG, flag, spoolfile
X
X/*
X** use the -a if you have it. This sometimes helps failed mail and warning
X** messages get back to where the mail originated.
X**
X** some versions of uux can't do '-a' - pick one of the next two definitions
X*/
X
X/*#define RMAIL(flags,from,sys) "%s -a%s %s - %s!rmail",UUX,from,flags,sys /* */
X#define RMAIL(flags,from,sys) "%s %s - %s!rmail",UUX,flags,sys /* */
X
X#define RARG(user) " '(%s)'",user
X#define RFROM(frm,now,host) "From %s %.24s remote from %s\n",frm,now,host
X
X
X#ifdef SENDMAIL
X
X /* We're letting sendmail do lots of work for us. */
X
X#define HANDLE JUSTUUCP /* see HANDLE definition below */
X#define ROUTING JUSTDOMAIN /* see ROUTING definition below */
X
X#define LMAIL(frm,sys) "%s -em -f'%s'",SENDMAIL,frm
X
X#define LARG(user) " '%s'",postmaster(user)
X#define RLARG(sys,frm) " '%s!%s'",sys,frm
X#define LFROM(frm,now,host) "From %s %.24s\n",frm,now
X
X#else /* !SENDMAIL */
X
X /* We don't have sendmail, so we'll do the work ourselves. */
X
X#define HANDLE ALL /* see HANDLE definition below */
X#define ROUTING ALWAYS /* see ROUTING definition below */
X
X#if defined(BSD) /* BSD local delivery agent */
X#define LMAIL(frm,sys) "/bin/mail"
X
X#elif defined(M_XENIX) /* Xenix local delivery agent (renamed) */
X#define EXECMAIL "/usr/lib/mail/execmail.x"
X#define LMAIL(frm,sys) "%s -m -f '%s'",EXECMAIL,frm
X
X#else /* System V local delivery agent */
X#define LMAIL(frm,sys) "/bin/lmail"
X
X#endif
X
X#define LARG(user) " '%s'",postmaster(user)
X#define RLARG(sys,frm) " '%s!%s'",sys,frm
X#define LFROM(frm,now,host) "From %s %.24s\n",frm,now
X
X#endif
X
X/*
X** The following definitions affect the queueing algorithm for uux.
X**
X** DEFQUEUE if defined the default is to queue uux mail
X**
X** QUEUECOST remote mail with a cost of less than QUEUECOST
X** will be handed to uux for immediate delivery.
X**
X** MAXNOQUEUE don't allow more than 'n' immediate delivery
X** jobs to be started on a single invocation of smail.
X**
X** GETCOST if defined, the paths file will be searched for
X** each address to discover the cost of the route.
X** this allows informed decisions about whether to
X** use the queue flags when calling uux. The price
X** is in the overhead of a paths file search for
X** addresses that are not going to be routed.
X*/
X
X#define DEFQUEUE /* default is to queue uux jobs */
X
X#define QUEUECOST 100 /* deliver immediately if the cost
X /* is DEDICATED+LOW or better */
X
X#define MAXNOQUEUE 2 /* max UUX_NOQUEUE jobs */
X
X#ifdef M_XENIX /* Xenix UUCP doesn't have a `spool this' option */
X#define UUX_QUEUE "" /* uux flag for queueing */
X#define UUX_NOQUEUE "" /* uux with immediate delivery */
X#else /* Normal UUCP */
X#define GETCOST /* search for cost */
X#define UUX_QUEUE "-r" /* uux flag for queueing */
X#define UUX_NOQUEUE "" /* uux with immediate delivery */
X#endif
X
X/*
X** Normally, all mail destined for the local host is delivered with a single
X** call to the local mailer, and all remote mail is delivered with one call
X** to the remote mailer for each remote host. This kind of 'batching' saves
X** on the cpu overhead.
X**
X** MAXCLEN is used to limit the length of commands that are exec'd by smail.
X** This is done to keep other program's buffers from overflowing, or to
X** allow for less intelligent commands which can take only one argument
X** at a time (e.g., 4.1 /bin/mail). To disable the batching, set MAXCLEN
X** a small value (like 0).
X*/
X
X#define MAXCLEN 128 /* longest command allowed (approx.)
X /* this is to keep other's buffers
X ** from overflowing
X */
X
X/*
X** PLEASE DON'T TOUCH THE REST
X*/
X
X#define SMLBUF 512 /* small buffer (handle one item) */
X#define BIGBUF 4096 /* handle lots of items */
X
X#define MAXPATH 32 /* number of elements in ! path */
X#define MAXDOMS 16 /* number of subdomains in . domain */
X#define MAXARGS 500 /* number of arguments */
X#ifndef NULL
X#define NULL 0
X#endif
X
X#define DEBUG if (debug==YES) (void) printf
X#define ADVISE if (debug!=NO) (void) printf
X#define error(stat,msg,a) { (void) fprintf(stderr, msg, a); exit(stat); }
X#define lower(c) ( isupper(c) ? c-'A'+'a' : c )
X
X
Xenum eform { /* format of addresses */
X ERROR, /* bad or invalidated format */
X LOCAL, /* just a local name */
X DOMAIN, /* user@domain or domain!user */
X UUCP, /* host!address */
X ROUTE, /* intermediate form - to be routed */
X SENT /* sent to a mailer on a previous pass */
X};
X
Xenum ehandle { /* what addresses can we handle? (don't kick to LMAIL) */
X ALL, /* UUCP and DOMAIN addresses */
X JUSTUUCP, /* UUCP only; set by -l */
X NONE /* all mail is LOCAL; set by -L */
X};
X
Xenum erouting { /* when to route A!B!C!D */
X JUSTDOMAIN, /* route A if A is a domain */
X ALWAYS, /* route A always; set by -r */
X REROUTE /* route C, B, or A (whichever works); set by -R */
X};
X
Xenum edebug { /* debug modes */
X NO, /* normal deliver */
X VERBOSE, /* talk alot */
X YES /* talk and don't deliver */
X};
X
X#ifdef BSD
X
X#include <strings.h>
X#include <sysexits.h>
X
X#else
X
X#include <string.h>
X#include "sysexits.h"
X#define index strchr
X#define rindex strrchr
X
X#endif
Xextern void exit(), perror();
Xextern unsigned sleep();
SHAR_EOF
if test 11012 -ne `wc -c < 'defs.h'`
then
echo 'shar: error transmitting "defs.h" (should have been 11012 characters) '
fi
chmod 664 'defs.h'
fi # end of overwriting check
:
echo 'shar: extracting "deliver.c" (12233 characters) '
if test -f 'deliver.c'
then
echo 'shar: will not overwrite existing file "deliver.c" '
else
sed 's/^X//' << \SHAR_EOF > 'deliver.c'
X/*
X** Deliver.c
X**
X** Routines to effect delivery of mail for rmail/smail.
X**
X*/
X
X/*
X** Modified for SCO Xenix by Chip Salzenberg (chip@ateng.UUCP).
X** Released to Usenet on 01 Dec 1987.
X*/
X
X#ifndef lint
Xstatic char *sccsid="@(#)deliver.c 2.5 (smail) 9/15/87";
X#endif
X
X# include <stdio.h>
X# include <sys/types.h>
X# include <sys/stat.h>
X# include <ctype.h>
X# include <signal.h>
X# include "defs.h"
X
Xextern char *myname; /* who does caller think we are?*/
Xextern int exitstat; /* set if a forked mailer fails */
Xextern enum edebug debug; /* how verbose we are */
Xextern char hostname[]; /* our uucp hostname */
Xextern char hostdomain[]; /* our host's domain */
Xextern enum ehandle handle; /* what we handle */
Xextern enum erouting routing; /* how we're routing addresses */
Xextern char *uuxargs; /* arguments given to uux */
Xextern int queuecost; /* threshold for queueing mail */
Xextern int maxnoqueue; /* max number of uucico's */
Xextern char *spoolfile; /* file name of spooled message */
Xextern FILE *spoolfp; /* file ptr to spooled message */
Xextern int spoolmaster; /* set if creator of spoolfile */
Xextern char nows[]; /* local time in ctime(3) format*/
Xextern char arpanows[]; /* local time in arpadate format*/
Xchar stderrfile[20]; /* error file for stderr traping*/
X
X/*
X**
X** deliver(): hand the letter to the proper mail programs.
X**
X** Issues one command for each different host of <hostv>,
X** constructing the proper command for LOCAL or UUCP mail.
X** Note that LOCAL mail has blank host names.
X**
X** The <userv> names for each host are arguments to the command.
X**
X** Prepends a "From" line to the letter just before going
X** out, with a "remote from <hostname>" if it is a UUCP letter.
X**
X*/
X
Xdeliver(argc, hostv, userv, formv, costv)
Xint argc; /* number of addresses */
Xchar *hostv[]; /* host names */
Xchar *userv[]; /* user names */
Xenum eform formv[]; /* form for each address */
Xint costv[]; /* cost vector */
X{
X FILE *out; /* pipe to mailer */
X FILE *popen(); /* to fork a mailer */
X#ifdef RECORD
X void record(); /* record all transactions */
X#endif
X#ifdef LOG
X void log();
X#endif
X char *mktemp();
X char from[SMLBUF]; /* accumulated from argument */
X char lcommand[SMLBUF]; /* local command issued */
X char rcommand[SMLBUF]; /* remote command issued */
X char scommand[SMLBUF]; /* retry command issued */
X char *command; /* actual command */
X char buf[SMLBUF]; /* copying rest of the letter */
X enum eform form; /* holds form[i] for speed */
X long size; /* number of bytes of message */
X char *flags; /* flags for uux */
X char *sflag; /* flag for smail */
X int i, j, status, retrying;
X char *c, *postmaster();
X int failcount = 0;
X int noqcnt = 0; /* number of uucico's started */
X char *uux_noqueue = UUX_NOQUEUE;/* uucico starts immediately */
X char *uux_queue = UUX_QUEUE; /* uucico job gets queued */
X off_t message;
X struct stat st;
X
X/*
X** rewind the spool file and read the collapsed From_ line
X*/
X (void) fseek(spoolfp, 0L, 0);
X (void) fgets(from, sizeof(from), spoolfp);
X if((c = index(from, '\n')) != 0) *c = '\0';
X message = ftell(spoolfp);
X
X/*
X** We pass through the list of addresses.
X*/
X stderrfile[0] = '\0';
X for(i = 0; i < argc; i++) {
X char *lend = lcommand;
X char *rend = rcommand;
X char *send = scommand;
X
X/*
X** If we don't have sendmail, arrange to trap standard error
X** for inclusion in the message that is returned with failed mail.
X*/
X (void) unlink(stderrfile);
X (void) strcpy(stderrfile, "/tmp/stderrXXXXXX");
X (void) mktemp(stderrfile);
X (void) freopen(stderrfile, "w", stderr);
X if(debug != YES) {
X (void) freopen(stderrfile, "w", stdout);
X }
X
X *lend = *rend = *send = '\0';
X
X/*
X** If form == ERROR, the address was bad
X** If form == SENT, it has been sent on a previous pass.
X*/
X form = formv[i];
X if (form == SENT) {
X continue;
X }
X/*
X** Build the command based on whether this is local mail or uucp mail.
X** By default, don't allow more than 'maxnoqueue' uucico commands to
X** be started by a single invocation of 'smail'.
X*/
X if(uuxargs == NULL) { /* flags not set on command line */
X if(noqcnt < maxnoqueue && costv[i] <= queuecost) {
X flags = uux_noqueue;
X } else {
X flags = uux_queue;
X }
X } else {
X flags = uuxargs;
X }
X
X retrying = 0;
X if(routing == JUSTDOMAIN) {
X sflag = "-r";
X } else if(routing == ALWAYS) {
X sflag = "-R";
X } else {
X sflag = "";
X }
X
X (void) sprintf(lcommand, LMAIL(from, hostv[i]));
X (void) sprintf(rcommand, RMAIL(flags, from, hostv[i]));
X
X/*
X** For each address with the same host name and form, append the user
X** name to the command line, and set form = ERROR so we skip this address
X** on later passes.
X*/
X /* we initialized lend (rend) to point at the
X * beginning of its buffer, so that at
X * least one address will be used regardless
X * of the length of lcommand (rcommand).
X */
X for (j = i; j < argc; j++) {
X if ((formv[j] != form)
X || (strcmpic(hostv[i], hostv[j]) != 0)
X || ((lend - lcommand) > MAXCLEN)
X || ((rend - rcommand) > MAXCLEN)) {
X continue;
X }
X
X /*
X ** seek to the end of scommand
X ** and add on a 'smail' command
X ** multiple commands are separated by ';'
X */
X
X send += strlen(send);
X if(send != scommand) {
X *send++ = ';' ;
X }
X
X (void) sprintf(send, RETRY(sflag));
X send += strlen(send);
X
X lend += strlen(lend);
X rend += strlen(rend);
X
X if (form == LOCAL) {
X (void) sprintf(lend, LARG(userv[j]));
X (void) sprintf(send, LARG(userv[j]));
X } else {
X (void) sprintf(lend, RLARG(hostv[i], userv[j]));
X (void) sprintf(send, RLARG(hostv[i], userv[j]));
X }
X
X (void) sprintf(rend, RARG(userv[j]));
X formv[j] = SENT;
X }
Xretry:
X/*
X** rewind the spool file and read the collapsed From_ line
X*/
X (void) fseek(spoolfp, message, 0);
X
X /* if the address was in a bogus form (usually DOMAIN),
X ** then don't bother trying the uux.
X **
X ** Rather, go straight to the next smail routing level.
X */
X if(form == ERROR) {
X static char errbuf[SMLBUF];
X (void) sprintf(errbuf,
X "address resolution ('%s' @ '%s') failed",
X userv[i], hostv[i]);
X command = errbuf;
X size = 0;
X goto form_error;
X }
X
X if (retrying) {
X command = scommand;
X } else if (form == LOCAL) {
X command = lcommand;
X } else {
X command = rcommand;
X if(flags == uux_noqueue) {
X noqcnt++;
X }
X }
X ADVISE("COMMAND: %s\n", command);
X
X/*
X** Fork the mailer and set it up for writing so we can send the mail to it,
X** or for debugging divert the output to stdout.
X*/
X
X/*
X** We may try to write on a broken pipe, if the uux'd host
X** is unknown to us. Ignore this signal, since we can use the
X** return value of the pclose() as our indication of failure.
X*/
X (void) signal(SIGPIPE, SIG_IGN);
X
X if (debug == YES) {
X out = stdout;
X } else {
X failcount = 0;
X do {
X out = popen(command, "w");
X if (out) break;
X /*
X * Fork failed. System probably overloaded.
X * Wait awhile and try again 10 times.
X * If it keeps failing, probably some
X * other problem, like no uux or smail.
X */
X (void) sleep(60);
X } while (++failcount < 10);
X }
X if(out == NULL) {
X exitstat = EX_UNAVAILABLE;
X (void) printf("couldn't execute %s.\n", command);
X continue;
X }
X
X size = 0;
X if(fstat(fileno(spoolfp), &st) >= 0) {
X size = st.st_size - message;
X }
X/*
X** Output our From_ line.
X*/
X if (form == LOCAL) {
X
X#if defined(SENDMAIL) || defined(EXECMAIL)
X /*
X * Smart transfer agent (sendmail or execmail)
X */
X (void) sprintf(buf, LFROM(from, nows, hostname));
X size += strlen(buf);
X (void) fputs(buf, out);
X
X#else
X /*
X * Dumb transfer agent
X */
X char *p;
X if((p=index(from, '!')) == NULL) {
X (void) sprintf(buf,
X LFROM(from, nows, hostname));
X size += strlen(buf);
X (void) fputs(buf, out);
X } else {
X *p = '\0';
X (void) sprintf(buf, RFROM(p+1, nows, from));
X size += strlen(buf);
X (void) fputs(buf, out);
X *p = '!';
X }
X#endif
X } else {
X (void) sprintf(buf, RFROM(from, nows, hostname));
X size += strlen(buf);
X (void) fputs(buf, out);
X }
X
X#if defined(SENDMAIL)
X/*
X** If using sendmail, insert a Received: line only for mail
X** that is being passed to uux. If not using sendmail, always
X** insert the received line, since sendmail isn't there to do it.
X*/
X if(command == rcommand && handle != ALL)
X#endif
X {
X (void) sprintf(buf,
X "Received: by %s (%s)\n\tid AA%05d; %s\n",
X hostdomain, VERSION,
X getpid(), arpanows);
X size += strlen(buf);
X (void) fputs(buf, out);
X }
X
X/*
X** Copy input.
X*/
X while(fgets(buf, sizeof(buf), spoolfp) != NULL) {
X (void) fputs(buf, out);
X }
X/*
X** Get exit status and if non-zero, set global exitstat so when we exit
X** we can indicate an error.
X*/
Xform_error:
X if (debug != YES) {
X if(form == ERROR) {
X exitstat = EX_NOHOST;
X } else if (status = pclose(out)) {
X exitstat = status >> 8;
X }
X /*
X * The 'retrying' check prevents a smail loop.
X */
X if(exitstat != 0) {
X /*
X ** the mail failed, probably because the host
X ** being uux'ed isn't in L.sys or local user
X ** is unknown.
X */
X
X if((retrying == 0) /* first pass */
X && (routing != REROUTE) /* have higher level */
X && (form != LOCAL)) { /* can't route local */
X /*
X ** Try again using a higher
X ** level of routing.
X */
X ADVISE("%s failed (%d)\ntrying %s\n",
X command, exitstat, scommand);
X exitstat = 0;
X retrying = 1;
X form = SENT;
X goto retry;
X }
X
X /*
X ** if we have no other routing possibilities
X ** see that the mail is returned to sender.
X */
X
X if((routing == REROUTE)
X || (form == LOCAL)) {
X
X /*
X ** if this was our last chance,
X ** return the mail to the sender.
X */
X
X ADVISE("%s failed (%d)\n",
X command, exitstat);
X
X (void) fseek(spoolfp, message, 0);
X#if defined(SENDMAIL) || defined(EXECMAIL)
X /* Mail is automatically returned
X ** by sendmail and execmail, so we
X ** need not do it again.
X */
X if(form != LOCAL)
X#endif
X {
X return_mail(from, command);
X }
X exitstat = 0;
X }
X }
X# ifdef LOG
X else {
X if (retrying == 0)
X log(command, from, size); /* */
X }
X# endif
X }
X }
X/*
X** Update logs and records.
X*/
X# ifdef RECORD
X (void) fseek(spoolfp, message, 0);
X record(command, from, size);
X# endif
X
X/*
X** close spool file pointer.
X** if we created it, then unlink file.
X*/
X (void) fclose(spoolfp);
X if(spoolmaster) {
X (void) unlink(spoolfile);
X }
X (void) unlink(stderrfile);
X}
X
X/*
X** return mail to sender, as determined by From_ line.
X*/
Xreturn_mail(from, fcommand)
Xchar *from, *fcommand;
X{
X char buf[SMLBUF];
X char domain[SMLBUF], user[SMLBUF];
X char *r;
X FILE *fp, *out, *popen();
X int i = 0;
X
X r = buf;
X
X (void) sprintf(r, "%s %s", SMAIL, VFLAG);
X r += strlen(r);
X
X if(islocal(from, domain, user)) {
X (void) sprintf(r, LARG(user));
X } else {
X (void) sprintf(r, RLARG(domain, user));
X }
X
X i = 0;
X do {
X out = popen(buf, "w");
X if (out) break;
X /*
X * Fork failed. System probably overloaded.
X * Wait awhile and try again 10 times.
X * If it keeps failing, probably some
X * other problem, like no uux or smail.
X */
X (void) sleep(60);
X } while (++i < 10);
X
X if(out == NULL) {
X (void) printf("couldn't execute %s.\n", buf);
X return;
X }
X
X (void) fprintf(out, "Date: %s\n", arpanows);
X (void) fprintf(out, "From: MAILER-DAEMON@%s\n", hostdomain);
X (void) fprintf(out, "Subject: failed mail\n");
X (void) fprintf(out, "To: %s\n", from);
X (void) fprintf(out, "\n");
X (void) fprintf(out, "======= command failed =======\n\n");
X (void) fprintf(out, " COMMAND: %s\n\n", fcommand);
X
X (void) fprintf(out, "======= standard error follows =======\n");
X (void) fflush(stderr);
X if((fp = fopen(stderrfile, "r")) != NULL) {
X while(fgets(buf, sizeof(buf), fp) != NULL) {
X (void) fputs(buf, out);
X }
X }
X (void) fclose(fp);
X (void) fprintf(out, "======= text of message follows =======\n");
X/*
X** Copy input.
X*/
X (void) fprintf(out, "From %s\n", from);
X while(fgets(buf, sizeof(buf), spoolfp) != NULL) {
X (void) fputs(buf, out);
X }
X (void) pclose(out);
X}
SHAR_EOF
if test 12233 -ne `wc -c < 'deliver.c'`
then
echo 'shar: error transmitting "deliver.c" (should have been 12233 characters) '
fi
chmod 664 'deliver.c'
fi # end of overwriting check
# End of shell archive
exit 0
--
Chip Salzenberg "chip@ateng.UUCP" or "{codas,uunet}!ateng!chip"
A T Engineering My employer's opinions are not mine, but these are.
"Gentlemen, your work today has been outstanding. I intend to recommend
you all for promotion -- in whatever fleet we end up serving." - JTK