Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!husc6!think!ames!amdahl!ihnp4!homxb!mtuxo!mtune!codas!ateng!chip From: chip@ateng.UUCP (Chip Salzenberg) Newsgroups: comp.unix.xenix,alt.sources Subject: Smail 2.5 vs. SCO Xenix System V: my solution (with sources) Message-ID: <114@ateng.UUCP> Date: Tue, 1-Dec-87 15:25:39 EST Article-I.D.: ateng.114 Posted: Tue Dec 1 15:25:39 1987 Date-Received: Sat, 5-Dec-87 02:30:59 EST Organization: A T Engineering, Tampa, FL Lines: 1122 Xref: mnetor comp.unix.xenix:1246 alt.sources:34 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#includeX 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 X#include X X#else X X#include 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 X# include X# include X# include X# include 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 , X** constructing the proper command for LOCAL or UUCP mail. X** Note that LOCAL mail has blank host names. X** X** The 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 " 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