rsalz@uunet.UU.NET (Rich Salz) (09/23/87)
Submitted-by: Larry Auton <clyde.ATT.COM!lda> Posting-number: Volume 11, Issue 71 Archive-name: smail3/Part03 # This is a shell archive. Remove anything before this line, then # unpack it by saving it in a file and typing "sh file". (Files # unpacked will be owned by you and have default permissions.) # # This archive contains: # lcasep.c main.c make.cf.sh map.c misc.c mkfnames.sh nptx.c patchlevel # pathproc.sh pw.c resolve.c smail.prompt str.c svbinmail.c sysexits.h # template.cf echo x - lcasep.c cat > "lcasep.c" << '//E*O*F lcasep.c//' /* ** convert the host name on a pathalias line to lower case */ #ifndef lint static char *sccsid="@(#)lcasep.c 2.5 (smail) 9/15/87"; #endif #include <stdio.h> #include <ctype.h> # define lower(c) ( isupper(c) ? c-'A'+'a' : c ) void exit(), perror(); main(argc, argv) int argc; char *argv[]; { FILE *ifp, *ofp; char buf[BUFSIZ]; register char *p; int c; extern int optind; extern char *optarg; ifp = stdin; ofp = stdout; while((c = getopt(argc, argv, "f:o:")) != EOF) { switch(c) { case 'f': if((ifp = fopen(optarg, "r")) == NULL) { (void) fprintf(stderr, "%s: can't open %s: ", argv[0], optarg); perror(""); exit(1); } break; case 'o': if((ofp = fopen(optarg, "w")) == NULL) { (void) fprintf(stderr, "%s: can't open %s: ", argv[0], optarg); perror(""); exit(1); } break; default: (void) fprintf(stderr, "usage: %s [-f file] [-o outfile]\n", argv[0]); exit(1); /* NOTREACHED */ break; } } while(fgets(buf, sizeof(buf), ifp) != NULL) { for(p = buf; *p != '\t' && *p != '\0' ; p++) { (void) fputc(lower(*p), ofp); } (void) fputs(p, ofp); } return(0); } //E*O*F lcasep.c// echo x - main.c cat > "main.c" << '//E*O*F main.c//' /* ** ** rmail/smail - UUCP mailer with automatic routing. ** ** Christopher Seiwald /+\ ** chris@cbosgd.att.com +\ ** January, 1985 \+/ ** */ #ifndef lint static char *sccsid="@(#)main.c 2.5 (smail) 9/15/87"; #endif /* ** ** usage: rmail [options] address... ** smail [options] address... ** options: ** -d debug - verbose and don't invoke mailers. ** -v verbose - just verbose. ** -A print mapped addresses. don't invoke mailers. ** -h hostname set hostname ** -H hostdomain set hostdomain (default hostname.MYDOM) ** -p pathfile path database filename ** -r force routing of host!address ** -R reroute even explicit path!user ** -l user@domain goes to local mailer ** -L all mail goes local ** -q number mail queueing cost threshold ** -m number limit on number of uux_noqueue jobs ** -u string string of flags for uux ** -F address name to substitute in From: line ** -a aliasfile aliases filename (not used with SENDMAIL) ** -n namelist list of full names for simple aliases */ #include <stdio.h> #include <ctype.h> #include "defs.h" int exitstat = 0; /* exit status, set by resolve, deliver */ enum edebug debug = NO; /* set by -d or -v option */ enum ehandle handle = HANDLE; /* which mail we can handle, see defs.h */ enum erouting routing = ROUTING;/* to route or not to route, see defs.h */ char hostname[SMLBUF] = ""; /* set by -h, defaults in defs.h */ char hostdomain[SMLBUF] = ""; /* set by -H, defaults in defs.h */ char hostuucp[SMLBUF] = ""; /* built with hostname+".UUCP" */ char *pathfile = PATHS; /* or set by -p */ char *uuxargs = NULL; /* or set by -u */ char *aliasfile = #ifdef ALIAS ALIAS; /* or set by -a */ #else NULL; #endif char *fnlist = #ifdef FULLNAME FULLNAME; /* or set by -n */ #else NULL; #endif int queuecost = QUEUECOST; /* or set by -q */ char *from_addr = NULL; /* or set by -F */ int maxnoqueue = MAXNOQUEUE; /* or set by -m */ int getcost = #ifdef GETCOST 1; /* get cost of path even if not routing */ #else 0; #endif char *spoolfile = NULL; /* name of the file containing letter */ FILE *spoolfp; /* file pointer to spoolfile */ int spoolmaster = 0; /* indicates 'control' of spoolfile */ void spool(); /* ** ** rmail/smail: mail stdin letter to argv addresses. ** ** After processing command line options and finding our host and domain ** names, we map addresses into <host,user,form,cost> sets. Then we deliver. ** */ main(argc, argv) int argc; char *argv[]; { char *hostv[MAXARGS]; /* UUCP neighbor */ char *userv[MAXARGS]; /* address given to host */ int costv[MAXARGS]; /* cost of resolved route */ enum eform formv[MAXARGS]; /* invalid, local, or uucp */ char *p; int c; int printaddr = 0; /* or set by -A */ int nargc; char **nargv, **alias(); char *optstr = "cdvArRlLH:h:p:u:q:a:n:m:f:F:"; extern char *optarg; extern int optind; /* ** see if we aren't invoked as rmail */ if((p = rindex(argv[0], '/')) == NULL) { p = argv[0]; } else { p++; } if(*p != 'r' ) { handle = ALL; } /* ** Process command line arguments */ while ((c = getopt(argc, argv, optstr)) != EOF) { switch ( c ) { case 'd': debug = YES; break; case 'v': debug = VERBOSE; break; case 'A': printaddr = 1; break; case 'F': from_addr = optarg; break; case 'r': routing = ALWAYS; break; case 'R': routing = REROUTE; break; case 'l': handle = JUSTUUCP; break; case 'L': handle = NONE; break; case 'f': spoolfile = optarg; break; case 'p': pathfile = optarg; break; case 'u': uuxargs = optarg; break; case 'a': aliasfile = optarg; break; case 'n': fnlist = optarg; break; case 'H': (void) strcpy(hostdomain, optarg); break; case 'h': (void) strcpy(hostname, optarg); break; case 'm': if(isdigit(*optarg)) { maxnoqueue = atoi(optarg); } break; case 'c': getcost = 1; break; case 'q': if(isdigit(*optarg)) { queuecost = atoi(optarg); } break; default: error( EX_USAGE, "valid flags are %s\n", optstr); } } if ( argc <= optind ) { error( EX_USAGE, "usage: %s [flags] address...\n", argv[0] ); } /* ** Get our default hostname and hostdomain. */ getmynames(); /* ** Spool the letter in a temporary file. */ nargc = argc - optind; if(printaddr == 0) { spool(nargc, &argv[optind]); } /* ** Do aliasing and fullname resolution */ nargv = alias(&nargc, &argv[optind]); /* ** Map argv addresses to <host, user, form, cost>. */ map(nargc, nargv, hostv, userv, formv, costv); /* ** If all we want it mapped addresses, print them and exit. */ if(printaddr) { int i; char abuf[SMLBUF]; for(i=nargc-1; i >= 0; i--) { if(formv[i] == ERROR) { (void) strcpy(abuf, nargv[i]); } else { build(hostv[i], userv[i], formv[i], abuf); } (void) fputs(abuf, stdout); if(i != 0) (void) putchar(' '); } (void) putchar('\n'); exit(0); } /* ** Deliver. */ deliver(nargc, hostv, userv, formv, costv); /* ** Exitstat was set if any resolve or deliver failed, otherwise 0. */ return( exitstat ); } //E*O*F main.c// echo x - make.cf.sh cat > "make.cf.sh" << '//E*O*F make.cf.sh//' #! /bin/sh # # @(#)make.cf.sh 2.5 (smail) 9/15/87 # cat <<!EOM! This script will prompt you for the automatically configurable parameters in the stock version of the sendmail configuration file. Naturally, any local extensions will have to be added manually. Clyde is a VAX running AT&T System V Release 2.0, with a port of sendmail. Clyde is a gateway for the domain .att.com. Below is a trace of the session that configured the sendmail.cf on clyde.ATT.COM: === !EOM! echo "press return to continue"; read foo cat <<!EOM! Enter Date (MM-DD-YY): 06-24-86 Enter This Host's Name: clyde Enter This Host's Official Domain: ATT.COM Enter Any Equivalent Domain Classes: ATT Enter Any Domains For Which This Host Is An Authority: ATT.UUCP Does This Host Have SMTP Connections (y/n)? no Enter Full Path to Executable That Will Provide Local Mail Delivery: /bin/lmail Is /bin/lmail A Berkeley Mailer [i.e., use -r to specify sender] (y/n)? no Will This Host Act As A Gateway Between Domains (y/n)? yes Are subdomains beneath this hosts' domain to be hidden (y/n)? yes === !EOM! # get date of configuration CF_DATE=`/bin/sh ./smail.prompt string "Enter Date (MM-DD-YY):"` # get host name CF_HOST=`/bin/sh ./smail.prompt string "Enter This Host's Name:"` # get host domain CF_DOMAIN=`/bin/sh ./smail.prompt string "Enter This Host's Official Domain:"` # get domain classes CF_DCLASS=`/bin/sh ./smail.prompt string "Enter Any Equivalent Domain Classes:"` # get domain authority CF_AUTHORITY=`/bin/sh ./smail.prompt string "Enter Any Domains For Which This Host Is An Authority:"` CF_SMTP=`/bin/sh ./smail.prompt yesno "Does This Host Have SMTP Connections (y/n)?"` if test "$CF_SMTP" = "yes" then #get list of local SMTP connections CF_SMTP=`/bin/sh ./smail.prompt file "Enter Full Path to File that Contains List of SMTP Connections:"` CF_SMTP="FE$CF_SMTP %s" else CF_SMTP="" fi # get path to local delivery agent CF_LOCALMAIL=`/bin/sh ./smail.prompt file "Enter Full Path to Executable That Will Provide Local Mail Delivery:"` CF_SYSTEM=`/bin/sh ./smail.prompt yesno "Is $CF_LOCALMAIL A Berkeley Mailer [i.e., use -r to specify sender] (y/n)?"` if test "$CF_SYSTEM" = "yes" then CF_SVMAIL="#" CF_BSMAIL="" else CF_SVMAIL="" CF_BSMAIL="#" fi CF_GATEWAY=`/bin/sh ./smail.prompt yesno "Will This Host Act As A Gateway Between Domains(y/n)?"` if test "$CF_GATEWAY" = "yes" then CF_GATEWAY="" else CF_GATEWAY="#" fi CF_HIDDENHOSTS=`/bin/sh ./smail.prompt yesno "Are subdomains beneath this hosts' domain to be hidden (y/n)?"` if test "$CF_HIDDENHOSTS" = "yes" then CF_HIDDENHOSTS="" else CF_HIDDENHOSTS="#" fi sed \ -e "s/CF_HOST/Dw$CF_HOST/" \ -e "s/CF_DOMAIN/DD$CF_DOMAIN/" \ -e "s/CF_AUTHORITY/DA$CF_AUTHORITY/" \ -e "s/CF_DCLASS/CDUUCP $CF_DCLASS/" \ -e "s;CF_SMTP;$CF_SMTP;" \ -e "s;CF_DATE;$CF_DATE;" \ -e "s;CF_LOCALMAIL;$CF_LOCALMAIL;" \ -e "s;CF_BSMAIL;$CF_BSMAIL;" \ -e "s;CF_SVMAIL;$CF_SVMAIL;" \ -e "s;CF_GATEWAY;$CF_GATEWAY;" \ -e "s;CF_HIDDENHOSTS;$CF_HIDDENHOSTS;" \ template.cf > sendmail.cf //E*O*F make.cf.sh// echo x - map.c cat > "map.c" << '//E*O*F map.c//' #ifndef lint static char *sccsid="@(#)map.c 2.5 (smail) 9/15/87"; #endif # include <stdio.h> # include <sys/types.h> # include "defs.h" extern int queuecost; /* ** ** map(): map addresses into <host, user, form, cost> sets. ** ** Calls resolve() for each address of argv. The result is hostv and ** userv arrays (pointing into buffers userz and hostz), and formv array. ** */ map(argc, argv, hostv, userv, formv, costv) int argc; /* address count */ char **argv; /* address vector */ char *hostv[]; /* remote host vector */ char *userv[]; /* user name vector */ enum eform formv[]; /* address format vector */ int costv[]; /* cost vector */ { int i, cost; enum eform resolve(); char *c; static char userbuf[BIGBUF], *userz; static char hostbuf[BIGBUF], *hostz; userz = userbuf; hostz = hostbuf; for( i=0; i<argc; i++ ) { #ifdef DEFQUEUE cost = queuecost+1; /* default is queueing */ #else cost = queuecost-1; /* default is no queueing */ #endif userv[i] = userz; /* put results here */ hostv[i] = hostz; if ( **argv == '(' ) { /* strip () */ ++*argv; c = index( *argv, ')' ); if (c) *c = '\0'; } /* here it comes! */ formv[i] = resolve(*argv++, hostz, userz, &cost); costv[i] = cost; userz += strlen( userz ) + 1; /* skip past \0 */ hostz += strlen( hostz ) + 1; } } //E*O*F map.c// echo x - misc.c cat > "misc.c" << '//E*O*F misc.c//' /* ** Miscellaneous support functions for smail/rmail */ #ifndef lint static char *sccsid="@(#)misc.c 2.5 (smail) 9/15/87"; #endif # include <stdio.h> # include <sys/types.h> # include <ctype.h> # include "defs.h" #ifdef BSD # include <sys/time.h> # include <sys/timeb.h> #else # include <time.h> # include <sys/utsname.h> #endif extern int exitstat; /* set if a forked mailer fails */ extern enum edebug debug; /* how verbose we are */ extern enum ehandle handle; /* what we handle */ extern char *uuxargs; /* arguments given to uux */ extern int queuecost; /* threshold for queueing mail */ extern int maxnoqueue; /* max number of uucico's */ extern enum erouting routing; /* when to route addresses */ extern char hostdomain[]; /* */ extern char hostname[]; /* */ extern char hostuucp[]; /* */ extern char *pathfile; /* location of path database */ extern char *spoolfile; /* file name of spooled message */ extern FILE *spoolfp; /* file ptr to spooled message */ extern int spoolmaster; /* set if creator of spoolfile */ extern struct tm *localtime(); struct tm *gmt, *loc; /* GMT and local time structure */ time_t now; /* current system time */ char nows[50]; /* time in ctime format */ char arpanows[50]; /* time in arpa format */ # ifdef LOG void log(command, from, size) char *command, *from; long size; { FILE *fd; char *logtime, tbuf[50]; int cmask; logtime = strcpy(tbuf, nows); logtime[16] = '\0'; logtime += 4; cmask = umask(0); fd = fopen(LOG, "a"); (void) umask(cmask); if (fd != NULL) { (void) fprintf(fd, "%s\t%ld\t%s\t%s\n", logtime, size, from, command); (void) fclose(fd); } } # endif # ifdef RECORD FILE * record(command, from, size) char *command, *from; long size; { FILE *fd; char *logtime, buf[SMLBUF]; int cmask; logtime = strcpy(buf, nows); logtime[16] = 0; logtime += 4; cmask = umask(0); fd = fopen(RECORD, "a"); (void) umask(cmask); if (fd != NULL) { (void) fprintf(fd, "%s: %s, from %s, %ld bytes\n", logtime, command, from, size); } while(fgets(buf, sizeof(buf), spoolfp) != NULL) { (void) fputs(buf, fd); } (void) fclose(fd); } # endif setdates() { time_t time(); struct tm *gmtime(); char *ctime(), *arpadate(); (void) time(&now); (void) strcpy(nows, ctime(&now)); gmt = gmtime(&now); loc = localtime(&now); (void) strcpy(arpanows, arpadate(nows)); } /* ** Note: This routine was taken from sendmail ** ** ARPADATE -- Create date in ARPANET format ** ** Parameters: ** ud -- unix style date string. if NULL, one is created. ** ** Returns: ** pointer to an ARPANET date field ** ** Side Effects: ** none ** ** WARNING: ** date is stored in a local buffer -- subsequent ** calls will overwrite. ** ** Bugs: ** Timezone is computed from local time, rather than ** from whereever (and whenever) the message was sent. ** To do better is very hard. ** ** Some sites are now inserting the timezone into the ** local date. This routine should figure out what ** the format is and work appropriately. */ char * arpadate(ud) register char *ud; { register char *p; register char *q; static char b[40]; extern char *ctime(); register int i; #ifndef BSD extern char *tzname[]; time_t t, time(); #else /* V7 and 4BSD */ struct timeb t; extern struct timeb *ftime(); extern char *timezone(); #endif /* ** Get current time. ** This will be used if a null argument is passed and ** to resolve the timezone. */ #ifndef BSD (void) time(&t); if (ud == NULL) ud = ctime(&t); #else /* V7 or 4BSD */ ftime(&t); if (ud == NULL) ud = ctime(&t.time); #endif /* ** Crack the UNIX date line in a singularly unoriginal way. */ q = b; p = &ud[8]; /* 16 */ if (*p == ' ') p++; else *q++ = *p++; *q++ = *p++; *q++ = ' '; p = &ud[4]; /* Sep */ *q++ = *p++; *q++ = *p++; *q++ = *p++; *q++ = ' '; p = &ud[22]; /* 1979 */ *q++ = *p++; *q++ = *p++; *q++ = ' '; p = &ud[11]; /* 01:03:52 */ for (i = 8; i > 0; i--) *q++ = *p++; /* -PST or -PDT */ #ifndef BSD p = tzname[localtime(&t)->tm_isdst]; #else p = timezone(t.timezone, localtime(&t.time)->tm_isdst); #endif if (p[3] != '\0') { /* hours from GMT */ p += 3; *q++ = *p++; if (p[1] == ':') *q++ = '0'; else *q++ = *p++; *q++ = *p++; p++; /* skip ``:'' */ *q++ = *p++; *q++ = *p++; } else { *q++ = ' '; *q++ = *p++; *q++ = *p++; *q++ = *p++; } p = &ud[0]; /* Mon */ *q++ = ' '; *q++ = '('; *q++ = *p++; *q++ = *p++; *q++ = *p++; *q++ = ')'; *q = '\0'; return (b); } /* * The user name "postmaster" must be accepted regardless of what * combination of upper and lower case is used. This function is * used to convert all case variants of "postmaster" to all lower * case. If the user name passed in is not "postmaster", it is * returned unchanged. */ char * postmaster(user) char *user; { static char *pm = "postmaster"; if(strcmpic(user, pm) == 0) { return(pm); } else { return(user); } } /* * Return 1 iff the string is "UUCP" (ignore case). */ isuucp(str) char *str; { if(strcmpic(str, "UUCP") == 0) { return(1); } else { return(0); } } /* ** sform(form) returns a pointer to a string that tells what 'form' means */ char * sform(form) enum eform form; { if(form == ERROR) return("ERROR"); if(form == LOCAL) return("LOCAL"); if(form == DOMAIN) return("DOMAIN"); if(form == UUCP) return("UUCP"); if(form == ROUTE) return("ROUTE"); return("UNKNOWN"); } /* ** ** getmynames(): what is my host name and host domain? ** ** Hostname set by -h, failing that by #define HOSTNAME, failing ** that by gethostname() or uname(). ** ** Hostdomain set by -h, failing that by #define HOSTDOMAIN, ** failing that as hostname.MYDOM, or as just hostname. ** ** See defs.h for the inside story. ** */ getmynames() { #ifdef HOSTNAME if (!*hostname) (void) strcpy(hostname, HOSTNAME); #endif #ifdef GETHOSTNAME if (!*hostname) gethostname(hostname, SMLBUF - 1); #endif #ifdef UNAME if (!*hostname) { struct utsname site; if (uname(&site) < 0) error(EX_SOFTWARE, "uname() call failed", 0); (void) strcpy(hostname, site.nodename); } #endif if (!*hostname) error(EX_SOFTWARE, "can't determine hostname.\n", 0); #ifdef HOSTDOMAIN if (!*hostdomain) (void) strcpy(hostdomain, HOSTDOMAIN); #endif #ifdef MYDOM if (!*hostdomain) (void) strcat(strcpy(hostdomain, hostname), MYDOM); #endif if (!*hostdomain) (void) strcpy(hostdomain, hostname); (void) strcat(strcpy(hostuucp, hostname), ".UUCP"); } //E*O*F misc.c// echo x - mkfnames.sh cat > "mkfnames.sh" << '//E*O*F mkfnames.sh//' #! /bin/sh # # @(#)mkfnames.sh 2.5 (smail) 9/15/87 # if test $# = 0 then sed 's/\(.*\):.*:.*:.*:\(.*\):.*:.*/\1 \2/' /etc/passwd else cat $* fi | # at this point, we have a list of login\tFull Name pairs nptx | lcasep | sort -u +0 -1 //E*O*F mkfnames.sh// echo x - nptx.c cat > "nptx.c" << '//E*O*F nptx.c//' #ifndef lint static char *sccsid = "@(#)nptx.c 2.5 (smail) 9/15/87"; #endif #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <pwd.h> #include "defs.h" #include <ctype.h> char *malloc(), *index(), *fullname(); void nptx(), free(), dotspace(); enum edebug debug; /* not used by nptx */ char *fnlist = NULL; /* not used by nptx */ main() { int i; char buf[SMLBUF], *p, *name, *last, *nick, *ctmp; while(gets(buf) != NULL) { /* line should be in form ** ** login First Last ** or ** login First Last(Nickname) ** */ if((p = index(buf, '\t')) == NULL) { (void) fprintf(stderr, "format error: %s\n", buf); continue; } *p++ = '\0'; name = fullname(p); dotspace(name); if (last = rindex(name, '.')) { last++; } else { last = NULL; } if ((nick = index(p, '(')) != NULL) { nick++; if ((ctmp = index(nick, ')')) == NULL) { nick = NULL; } else { *ctmp = '\0'; } } nptx(buf, name); if((last != NULL) && (nick != NULL)) { i=strlen(nick) + strlen(last) + 2; if((name = malloc(i)) != NULL) { (void) strcpy(name, nick); (void) strcat(name, "."); (void) strcat(name, last); dotspace(name); nptx(buf, name); free(name); } } } return(0); } void dotspace(s) char *s; { register char *p, *t; /* turn whitespace to '.' */ for(p = s; *p != '\0'; p++) { if((*p == ' ') || (*p == '\t')) { *p = '.'; } } /* elide leading '.'s */ for(p = s; *p == '.' ; p++) ; /* elide mulitple '.'s and all "'"s */ for(t = s; *p != '\0'; p++, t++) { *t = *p; if(*t == '\'') { t--; continue; } if(*p == '.') { while(*(++p) == '.') ; p--; } } *t = '\0'; /* elide trailing '.' */ if((t > s) && (*(--t) == '.')) *t = '\0'; } void nptx(login, name) char *login, *name; { int i,j,k,N,lim,mask; int ii,ji,ki,Ni,limi,maski; char nl[11][100], il[11][100]; char *pi, *p, *rindex(); char buf[100]; char bufi[100]; if((name == NULL) || (*name == '\0')) { return; } for(i=0; i < 10; i++) { if((p = rindex(name, '.')) == NULL) break; (void) strcpy(nl[i], p+1); *p = NULL; } (void) strcpy(nl[i], name); while((strcmpic(nl[i], "Mr" ) == 0) || (strcmpic(nl[i], "Dr" ) == 0) || (strcmpic(nl[i], "Mrs" ) == 0) || (strcmpic(nl[i], "Miss") == 0) || (strcmpic(nl[i], "Ms" ) == 0)) { i--; } while((strcmpic(nl[0], "Jr") == 0) || (strcmpic(nl[0], "Sr") == 0)) { for(j=0; j < i; j++) { (void) strcpy(nl[j], nl[j+1]); } i--; } N = i; lim = 1 << (N+1); for(mask = 1 << N ; mask < lim ; mask++) { buf[0] = '\0'; for(j = 1, k = N; j < lim; j <<=1, k--) { if(j & mask) { (void) strcat(buf, nl[k]); (void) strcat(buf, "."); } } if((p = rindex(buf, '.')) != NULL) { *p = '\0'; } for(ii=0; ii < 10; ii++) { if((pi = rindex(buf, '.')) == NULL) break; (void) strcpy(il[ii], pi+1); *pi = NULL; } (void) strcpy(il[ii], buf); Ni = ii; limi = 1 << (Ni+1); for(maski = 1 << Ni /* 0 */ ; maski < limi ; maski++) { bufi[0] = '\0'; for(ji = 1, ki = Ni; ji < limi; ji <<=1, ki--) { if(ji & maski) { (void) strcat(bufi, il[ki]); } else { char init[3]; init[0] = il[ki][0]; init[1] = '\0'; (void) strcat(bufi, init); } (void) strcat(bufi, "."); } if((pi = rindex(bufi, '.')) != NULL) { *pi = '\0'; } #ifdef DOT_REQD if(index(bufi, '.') == NULL) { continue; } #endif /* DOT_REQD */ (void) printf("%s\t%s\n",bufi, login); /* */ } } } //E*O*F nptx.c// echo x - patchlevel cat > "patchlevel" << '//E*O*F patchlevel//' Patch #: 00 //E*O*F patchlevel// echo x - pathproc.sh cat > "pathproc.sh" << '//E*O*F pathproc.sh//' # # @(#)pathproc.sh 2.5 (smail) 9/15/87 # # This script will do all that's necessary for # transforming the output of pathalias -f into # the format of a 'paths' file for smail. # # format of the pathalias -f output is # cost host route # # format of a 'paths' file for smail is # host route first_hop_cost # # move cost field to end of line # sed 's/\(.*\) \(.*\) \(.*\)/\2 \3 \1/'| # # convert target domain/host to lower case # lcasep | # # sort the stream # sort //E*O*F pathproc.sh// echo x - pw.c cat > "pw.c" << '//E*O*F pw.c//' #ifndef lint static char *sccsid = "@(#)pw.c 2.5 (smail) 9/15/87"; #endif #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <pwd.h> #include "defs.h" #include <ctype.h> char *malloc(); void free(); typedef struct pw_node pwlist; struct pw_node { char *lname; /* login name */ char *fname; /* full name */ int uid; /* user-id */ char *home; /* login name */ pwlist *vlink; /* link to next item */ }; pwlist *pwhead; /* head of linked list */ pwlist *pwparse(); /* head of linked list */ #define PNULL ((pwlist *) 0) char * pwfnam(user) char *user; { pwlist *f; /* ** check for previously cached user */ for(f=pwhead; f != NULL; f=f->vlink) { if(strcmp(user, f->lname) == 0) { return(f->fname); } } /* ** not found parse the password file */ while((f=pwparse()) != PNULL) { if(strcmp(user, f->lname) == 0) { return(f->fname); } } return(NULL); } char * pwuid(uid) int uid; { pwlist *f; /* ** check for previously cached user */ for(f=pwhead; f != NULL; f=f->vlink) { if(uid == f->uid) { return(f->lname); } } /* ** not found parse the password file */ while((f=pwparse()) != PNULL) { if(uid == f->uid) { return(f->lname); } } return(NULL); } #ifndef SENDMAIL char * tilde(user) char *user; { pwlist *f; /* ** check for previously cached user */ for(f=pwhead; f != NULL; f=f->vlink) { if(strcmp(user, f->lname) == 0) { return(f->home); } } /* ** not found parse the password file */ while((f=pwparse()) != PNULL) { if(strcmp(user, f->lname) == 0) { return(f->home); } } return(NULL); } #endif /* not SENDMAIL */ char * fullname(gecos) char *gecos; { static char fname[SMLBUF]; register char *cend; (void) strcpy(fname, gecos); if (cend = index(fname, ',')) *cend = '\0'; if (cend = index(fname, '(')) *cend = '\0'; /* ** Skip USG-style 0000-Name nonsense if necessary. */ if (isdigit(*(cend = fname))) { if ((cend = index(fname, '-')) != NULL) cend++; else /* ** There was no `-' following digits. */ cend = fname; } return (cend); } pwlist * pwparse() { pwlist *f; char *p, *name; struct passwd *pwent, *getpwent(); unsigned int i; static int pw_eof = 0; if((pw_eof == 1) || ((pwent = getpwent()) == (struct passwd *) NULL)) { pw_eof = 1; return(PNULL); } /* ** Get an entry from the password file. ** Parse relevant strings. */ f = (pwlist *) malloc(sizeof(pwlist)); if(f == PNULL) return(PNULL); f->vlink = pwhead; pwhead = f; f->uid = pwent->pw_uid; i=strlen(pwent->pw_name)+1; p = malloc(i); if(p == NULL) return(PNULL); f->lname = strcpy(p, pwent->pw_name); i=strlen(pwent->pw_dir)+1; p = malloc(i); if(p == NULL) return(PNULL); f->home = strcpy(p, pwent->pw_dir); name = fullname(pwent->pw_gecos); i=strlen(name)+1; p = malloc(i); if(p == NULL) return(PNULL); f->fname = strcpy(p, name); return(f); } #ifdef FULLNAME /* ** Resolve a full name to a login name. ** Not too much smarts here. */ char * res_fname(user) register char *user; { long pos, middle, hi, lo; static long pathlength = 0; register char *s; int c; static FILE *file; int flag; char namebuf[SMLBUF], *path; extern enum edebug debug; extern char *fnlist; DEBUG("res_fname: looking for '%s'\n", user); if(pathlength == 0) { /* open file on first use */ if((file=fopen(fnlist, "r")) == NULL) { DEBUG( "can't access %s.\n", fnlist); pathlength = -1; } else { (void) fseek(file, 0L, 2); /* find length */ pathlength = ftell(file); } } if(pathlength == -1 ) return(NULL); lo = 0; hi = pathlength; path = namebuf; (void) strcpy( path, user ); (void) strcat( path, "\t" ); for( ;; ) { pos = middle = ( hi+lo+1 )/2; (void) fseek( file, pos, 0 ); /* find midpoint */ if (pos != 0) /* to beginning of next line */ while( ( c=getc( file ) ) != EOF && c != '\n' ); for( flag = 0, s = path; flag == 0; s++ ) { /* match??? */ if ( *s == '\0' ) { goto solved; } c = getc( file ); flag = lower( c ) - lower( *s ); } if (lo >= middle) /* failure? */ return(NULL); if(c != EOF && flag < 0) /* close window */ lo = middle; else hi = middle - 1; } /* ** Now just copy the result. */ solved: while(((c = getc(file)) != EOF) && (c != '\t') && (c != '\n')) { *path++ = c; } if(path == namebuf) { /* NULL alias field */ return(NULL); } *path = '\0'; if((path = malloc((unsigned) strlen(namebuf)+1)) == NULL) { return(NULL); /* sorry, no memory */ } (void) strcpy(path, namebuf); return(path); } #endif /* FULLNAME */ //E*O*F pw.c// echo x - resolve.c cat > "resolve.c" << '//E*O*F resolve.c//' /* ** ** Resolve.c ** ** Routes then resolves addresses into UUCP or LOCAL. ** */ #ifndef lint static char *sccsid="@(#)resolve.c 2.5 (smail) 9/15/87"; #endif #include <ctype.h> #include <stdio.h> #include "defs.h" extern int exitstat; /* set if address doesn't resolve */ extern enum ehandle handle; /* what mail we can handle */ extern enum edebug debug; /* verbose and debug modes */ extern enum erouting routing; /* when to route addresses */ extern char hostdomain[]; /* */ extern char hostname[]; /* */ extern char *pathfile; /* location of path database */ extern int getcost; /* get path cost even if not routing */ char *sform(); /* ** ** rsvp(): how to resolve addresses. ** ** After parsing an address into <form>, the resolved form will be ** rsvp( form ). If == ROUTE, we route the parsed address and parse again. ** */ # define rsvp(a) table[(int)a][(int)handle] enum eform table[5][3] = { /* all justuucp none */ { ERROR, ERROR, ERROR }, /* error */ { LOCAL, LOCAL, LOCAL }, /* local */ { ROUTE, LOCAL, LOCAL }, /* domain */ { UUCP, UUCP, LOCAL }, /* uucp */ { ERROR, ERROR, ERROR }}; /* route */ /* ** ** resolve(): resolve addresses to <host, user, form>. ** ** This is a gnarly piece of code, but it does it all. Each section ** is documented. ** */ enum eform resolve( address, domain, user , cost) char *address; /* the input address */ char *domain; /* the returned domain */ char *user; /* the returned user */ int *cost; /* the returned cost */ { enum eform form; /* the returned form */ enum eform parse(); /* to crack addresses */ int parts; /* to ssplit addresses */ char *partv[MAXPATH]; /* " " " */ char temp[SMLBUF]; /* " " " */ int i; /* ** If we set REROUTE and are prepared to deliver UUCP mail, we split the ** address apart at !'s and try to resolve successively larger righthand ** substrings until we succeed. Otherwise, we just resolve the whole thing ** once. */ if ((routing == REROUTE) && (rsvp( UUCP ) == UUCP)) { parts = ssplit( address, '!', partv ); } else { parts = 1; partv[0] = address; } /* ** This for(i) loop selects successively larger ** righthand substrings of the address. */ for( i = parts - 1; i >= 0; i-- ) { /* ** Parse the address. */ (void) strcpy( temp, partv[i] ); form = parse( temp, domain, user ); DEBUG("resolve: parse address '%s' = '%s' @ '%s' (%s)\n", temp,user,domain,sform(form)); /* ** If we are looking at a substring (that's not the entire string) ** which parses to a LOCAL address, we skip to the next larger substring. */ if((i != 0) && (form == LOCAL)) continue; /* ** Routing, when required, is the next step. ** We route the address if we have a ROUTE form ** or if we have a UUCP form and we are told to ** route ALWAYS or REROUTE (i.e., routing != JUSTDOMAIN) */ if((rsvp( form ) == ROUTE) ||((rsvp( form ) == UUCP) && (routing != JUSTDOMAIN ))) { int look_smart = 0; if((routing == REROUTE) && (i == 0)) { look_smart = 1; /* last chance */ } /* route() puts the new route in 'temp' */ if(route(domain,user,look_smart,temp,cost) != EX_OK) { continue; /* If routing fails, try /* next larger substring. /* */ } /* ** After routing, reparse the new route into domain and user. */ form = parse( temp, domain, user ); DEBUG("resolve: parse route '%s' = '%s' @ '%s' (%s)\n", temp,user,domain,sform(form)); } else if((getcost) && (rsvp(form) == UUCP)) { /* get the cost of the route ** even if we're not going route the mail. ** this allows smart decisions about using ** the -r flag to uux when we're not routing. */ char junk[SMLBUF]; if(route(domain,user,0,junk,cost) != EX_OK) { continue; /* If routing fails, try /* next larger substring. /* */ } } break; /* route is resolved */ } /* ** For LOCAL mail in non-local format, we rewrite the full address into ** <user> and leave <domain> blank. */ if ((rsvp( form ) == LOCAL) && (form != LOCAL )) { build( domain, user, form, temp ); (void) strcpy( user, temp ); (void) strcpy( domain, "" ); form = LOCAL; } /* ** If we were supposed to route an address but failed (form == ERROR), ** or after routing we are left with an address that still needs to ** be routed (rsvp( form ) == ROUTE), complain. */ if ((form == ERROR) || (rsvp( form ) == ROUTE )) { exitstat = EX_NOHOST; ADVISE("resolve failed '%s' = '%s' @ '%s' (%s)\n", address, user, domain, sform(form)); form = ERROR; } else { ADVISE("resolve '%s' = '%s' @ '%s' (%s)\n", address, user, domain, sform(form)); } return ( form ); } /* ** ** route(): route domain, plug in user. ** ** Less complicated than it looks. Each section is documented. ** */ route(domain, user, look_smart, result, cost) char *domain; /* domain or host name */ char *user; /* user name */ int look_smart; /* do we try to route through a smarter host? */ char *result; /* output route */ int *cost; /* cost of output route */ { int uucpdom = 0; int domains, step; /* to split domain */ char *domainv[MAXDOMS]; /* " " " */ char temp[SMLBUF], path[SMLBUF]; /* ** Fully qualify the domain, and then strip the last (top level domain) ** component off, so that we look it up separately. */ temp[0] = '.'; (void) strcpy(temp+1, domain ); domains = ssplit( temp+1, '.', domainv ); /* ** check target domain for the local host name and host domain. ** if it matches, then skip the lookup in the database. ** this prevents mail loops for cases where SMARTHOST is defined ** in the routing table, but the local host is not. It also is ** a little faster when the local host is the target domain. */ if((strcmpic(domain, hostname) == 0) || (strcmpic(domain, hostdomain) == 0)) { step = 0; *cost = 0; (void) strcpy(path, "%s"); DEBUG("route: '%s' is local\n", domain); goto route_complete; } /* If the domain ends in .UUCP, trim that off. */ if((domains > 0) && isuucp(domainv[domains-1])) { domains--; domainv[domains][-1] = '\0'; uucpdom = 1; } /* ** Try to get the path for successive components of the domain. ** Example for osgd.cb.att.uucp: ** osgd.cb.att ** cb.att ** att ** uucp ( remember stripping top level? ) ** SMARTHOST ** Returns with error if we find no path. */ for(step = 0; (step < domains); step++) { if((getpath(domainv[step]-1, path, cost) == EX_OK) /* w/ dot */ || (getpath(domainv[step] , path, cost) == EX_OK))/* no dot */ break; } if(step == domains) { /* ** we've looked at each component of the domain without success */ /* ** If domain is a UUCP address, look for a UUCP gateway. */ if((uucpdom == 0) || (getpath(".UUCP", path, cost) != EX_OK)) { /* ** The domain not is a UUCP address, or we can't ** find a UUCP gateway. If this is our last chance, ** look for a smarter host to deliver the mail. */ if((look_smart == 0) || (getpath(SMARTHOST, path, cost) != EX_OK)) { /* ** All our efforts have been in vain. ** Tell them the bad news. */ DEBUG("route '%s' failed\n", domain); return( EX_NOHOST ); } } } route_complete: DEBUG("route: '%s' (%s) = '%s' (%d)\n", domain, domainv[step]?domainv[step]:"NULL", path, *cost); /* ** If we matched on the entire domain name, this address is fully resolved, ** and we plug <user> into it. If we matched on only part of the domain ** name, we plug <domain>!<user> in. */ build(domain, user, (step == 0) ? LOCAL : UUCP, temp); (void) sprintf(result, path, temp); return( EX_OK ); } //E*O*F resolve.c// echo x - smail.prompt cat > "smail.prompt" << '//E*O*F smail.prompt//' # # @(#)smail.prompt 2.5 (smail) 9/15/87 # loop=true while test $loop = true do case "$1" in string) echo "$2" 1>&2 read ans if test ! -z "$ans" then echo $ans loop=false; fi ;; file) echo "$2" 1>&2 read ans case "$ans" in /*) if test -f "$ans" then echo $ans loop=false; else echo "file '$ans' not found" 1>&2 fi ;; *) echo "must give FULL PATH to file" 1>&2 ;; esac ;; yesno) echo "$2" 1>&2 read ans case "$ans" in y|Y|yes|Yes|YES) echo "yes" loop=false ;; n|N|no|No|NO) echo "no" loop=false ;; *) echo "Please enter yes or no" 1>&2 ;; esac ;; *) echo "usage: $0 string|yesno prompt_message" 1>&2 echo BOGUS_PROMPT_STRING loop=false ;; esac done //E*O*F smail.prompt// echo x - str.c cat > "str.c" << '//E*O*F str.c//' #ifndef lint static char *sccsid="@(#)str.c 2.5 (smail) 9/15/87"; #endif #include "defs.h" #include <ctype.h> /* ** strncmpic: string compare, ignore case, stop after 'n' chars */ strncmpic(s1, s2, n) char *s1, *s2; int n; { register char *u = s1; register char *p = s2; while((n > 0) && (*p != '\0')) { /* chars match or only case different */ if(lower(*u) == lower(*p)) { p++; /* examine next char */ u++; } else { break; /* no match - stop comparison */ } n--; } if(n > 0) { return(lower(*u) - lower(*p)); /* return "difference" */ } else { return(0); } } /* ** strcmpic: string compare, ignore case */ strcmpic(s1, s2) char *s1, *s2; { register char *u = s1; register char *p = s2; while(*p != '\0') { /* chars match or only case different */ if(lower(*u) == lower(*p)) { p++; /* examine next char */ u++; } else { break; /* no match - stop comparison */ } } return(lower(*u) - lower(*p)); /* return "difference" */ } //E*O*F str.c// echo x - svbinmail.c cat > "svbinmail.c" << '//E*O*F svbinmail.c//' #ifndef lint static char *sccsid = "@(#)svbinmail.c 2.5 (smail) 9/15/87"; #endif /* */ /* This program will be used in place of /bin/mail on SVR2 sites. /* It looks at the arguments and decides whether to call /* SENDER for sending mail, or READER for reading mail. /* /* before installing as /bin/mail, move the stock /bin/mail to /bin/lmail /* /* */ #include <stdio.h> #include "defs.h" #ifdef SENDMAIL #define SENDER SENDMAIL #else #define SENDER "/bin/rmail" #endif #define READER "/bin/lmail" #define TRUE 1 #define FALSE 0 char prog[128]; void perror(), exit(), usage(); main(argc, argv) int argc; char *argv[]; { extern int optind; extern char *optarg; int i, j, c; int reading, sending; reading = sending = FALSE; (void) strcpy(prog, argv[0]); if(argc == 1) { reading = TRUE; } else { while((c = getopt(argc, argv, "epqrtf:")) != EOF) { switch(c) { case 'e': case 'p': case 'q': case 'r': case 'f': reading = TRUE; break; case 't': sending = TRUE; break; default: usage(); return(1); } } } /* any arguments left over -> sending */ if(argc > optind) { sending = TRUE; } if((reading == TRUE) && (sending == TRUE)) { usage(); return(1); } if(sending == TRUE) { argv[0] = SENDER; for(i = 1, j = optind; j < argc; i++, j++) { argv[i] = argv[j]; } argv[i] = NULL; } else { argv[0] = READER; } (void) execvp(argv[0], argv); (void) fprintf(stderr, "%s: execvp(\"%s\", argv) failed: ", prog, argv[0]); perror(""); return(1); } void usage() { (void) fprintf(stderr, "usage:\t%s [ -epqr ] [ -f file ]\n", prog); (void) fprintf(stderr, "\t%s [ -t ] persons\n", prog); } //E*O*F svbinmail.c// echo x - sysexits.h cat > "sysexits.h" << '//E*O*F sysexits.h//' /* ** @(#)sysexits.h 2.5 (smail) 9/15/87 */ # define EX_OK 0 /* successful termination */ # define EX_USAGE 64 /* command line usage error */ # define EX_NOHOST 68 /* host name unknown */ # define EX_UNAVAILABLE 69 /* service unavailable */ # define EX_SOFTWARE 70 /* internal software error */ # define EX_OSFILE 72 /* critical OS file missing */ # define EX_CANTCREAT 73 /* can't create (user) output file */ # define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ //E*O*F sysexits.h// echo x - template.cf cat > "template.cf" << '//E*O*F template.cf//' ############################################################ # # SENDMAIL CONFIGURATION FILE # # supports internet style addressing # over UUCP and ethernet links. # # A product of the UUCP Project. # # @(#)template.cf 2.5 (smail) 9/15/87 # ############################################################ ############################################################ # # Local configuration options - HINTS # # Host name and domain name macros. # # Dw sets $w # DD sets $D # CD sets $=D # # $D and $=D list all domains in which this host sits. # $D goes into outbound addresses, i.e. "user@$w.$D". # $A is another domain for which this host is 'authoritative' # it will will be turned into $D. CF_HOST CF_DOMAIN CF_AUTHORITY CF_DCLASS # Preemptive ether connections. We prefer these connections # over both designated transport mechanisms and the general depository. # You can add more classes (here and in S0). # /etc/hosts.smtp might be a link to /etc/hosts # CF_SMTP # Mock top-level domain names. These name designate a transport mechanism # and appear internally only, set in S3, used in S0, and removed in S4 and # (possibly) the ruleset for the particular mailer. CTETHER UUX # Relay host. Used at the end of S0 as the general depository for # addresses which didn't resolve locally. DRrelay # # End Local configuration options # ############################################################ ############################################################ # # General configuration information # ############################################################ DVsmail2.5/CF_DATE ########################## # Special macros # ########################## # official hostname Dj$w.$D # my name DnMAILER-DAEMON # UNIX header format DlFrom $g $d # delimiter (operator) characters Do.:%@!^=/[] # format of a total name Dq$g$?x ($x)$. # SMTP login message De$j Sendmail $v/$V ready at $b ################### # Options # ################### # location of alias file OA/usr/lib/aliases # default delivery mode (deliver in background) Odbackground # (don't) connect to "expensive" mailers #Oc # temporary file mode OF0644 # default GID Og1 # location of help file OH/usr/lib/sendmail.hf # log level OL9 # default messages to old style Oo # queue directory OQ/usr/spool/mqueue # read timeout -- violates protocols Or2h # status file OS/usr/lib/sendmail.st # queue up everything before starting transmission Os # default timeout interval OT3d # time zone names (V6 only) OtPST,PDT # default UID Ou1 # wizard's password OWvoidpasswords ############################### # Message precedences # ############################### Pfirst-class=0 Pspecial-delivery=100 Pjunk=-100 ######################### # Trusted users # ######################### Troot Tdaemon Tuucp Tnetwork ############################# # Format of headers # ############################# #H?P?Return-Path: <$g> HReceived: $?sfrom $s $.by $j ($v/$V) id $i; $b H?D?Resent-Date: $a H?D?Date: $a H?F?Resent-From: $q H?F?From: $q H?x?Full-Name: $x HSubject: # HPosted-Date: $a # H?l?Received-Date: $b H?M?Resent-Message-Id: <$t.$i@$j> H?M?Message-Id: <$t.$i@$j> ############################################################ # # REWRITING RULES # ########################### # # # Name Canonicalization # # # ########################### S3 # basic textual canonicalization R<> $@@ turn into magic token R$*<$+>$* $2 basic RFC821/822 parsing R$+ at $+ $1@$2 "at" -> "@" for RFC 822 R$*<$*>$* $1$2$3 in case recursive # handle route-addr <@a,@b,@c:user@d> R@$+,$+ @$1:$2 change all "," to ":" R@$+:$+ $@<@$1>:$2 handle <route-addr> R$+:$*;@$+ $@$1:$2;@$3 list syntax # Rewrite address into a domain-based address. Any special mock domain names # (like UUX) should be defined on the CT line and removed (if necessary) # in S4. You can use them in S0 for designated transport mechanisms. # Delimiters with precedence over @. Add yours here. # The @ delimiter. Leave this alone. R$+@$+ $:$1<@$2> focus on domain R$+<$+@$+> $1$2<@$3> move gaze right R$+<@$+> $@$1<@$2> already canonical # Delimiters with precedence below @. Add yours here. R$+^$+ $1!$2 convert ^ to ! R$-!$+ $@$2<@$1.UUX> resolve uucp names R$+.!$+ $@$2<@$1> domain.!host R$+!$+ $@$2<@$1> domain!host # % is a low precedence @. R$*%$* $@$>3$1@$2 %->@ and retry ############################################################ # # RULESET ZERO PREAMBLE # ############################################################ S0 # first make canonical R$*<$*>$* $1$2$3 defocus R$+ $:$>3$1 make canonical # handle special cases..... R@ $#local$:MAILER-DAEMON handle <> form R$*<@[$+]>$* $#ether$@[$2]$:$1@[$2]$3 numeric internet spec # strip local stuff R$*<@$-.$w.$D>$* $1<@$2>$3 thishost.mydom CF_GATEWAYR$*<@$-.$D>$* $1<@$2>$3 mydom R$*<@$-.$w.$=D>$* $1<@$2>$4 thishost.anydom R$*<@$-.$w.$A>$* $1<@$2>$3 thishost.anotherdom R$*<@$-.$A>$* $1<@$2>$3 anotherdom R$*<@$-.$w.$=T>$* $1<@$2>$4 thishost.mockdom CF_GATEWAYR$*<$*$w>$* $1<$2>$3 thishost R$*<$*.>$* $1<$2>$3 drop trailing dot R<@>:$+ $@$>0$1 strip null route, retry R$+<@> $@$>0$1 strip null addr, retry ############################################### # Machine dependent part of ruleset zero # ############################################### # Preemption: for a host on a known link turn the domain spec into a # mock domain indicating the link. One set of these rules for each of # the F classes listed in the local configuration options. R$*<$*$=E.$D>$* $:$1<$2$3.ETHER>$4 etherhost.mydomain R$*<$*$=E.$=D>$* $:$1<$2$3.ETHER>$5 etherhost.anydomain R$*<$*$=E.$A>$* $:$1<$2$3.ETHER>$4 etherhost.anotherdomain R$*<$*$=E.$=T>$* $:$1<$2$3.ETHER>$5 etherhost.mock-domain R$*<$*$=E>$* $:$1<$2$3.ETHER>$4 etherhost # Designated delivery: use the indicated transport mechanism. One of # these rules for each of the mock domains defined in $=T. You can # remove these if you just want general disposition. HINTS. # Designated delivery: R$*<@$=U.UUX>$* $#uux$@$2$:$1$3 known uucphost R$*<@$=E$+.ETHER>$* $#ether$@$2$:$1@$2$4 known etherhost R$*<@$+.ETHER>$* $#ether$@$2$:$1@$2$3 etherhost # throw out mock domain name now R$*<$*.$=T>$* $1<$2>$4 # General disposition of remote mail (comment out all but one). You # might add to this list, if you have other "smarter" mailers. HINTS. R$*<@$->:$+ $#uux$@$2$:$1$3 forward to $2 R$*<@$*>$* $#uux$@$2$:$1$3 hand to uucp #R$*<@$*>$* $#uux$@$R$:$1@$2$3 hand to uucp relay #R$*<@$*>$* $#ether$@$R$:$1@$2$3 hand to ether relay #R$*<$*>$* $#error$:unknown address $1$2$3 don't hand anywhere # local delivery R$+ $#local$:$1 user ############################################################ # # Local and Program Mailer specification # ############################################################ CF_SVMAILMlocal, P=CF_LOCALMAIL, F=lsDFMhumSU, S=10, R=20, A=rmail $u CF_BSMAILMlocal, P=CF_LOCALMAIL, F=rlsDFMmn, S=10, R=20, A=mail -d $u Mprog, P=/bin/sh, F=lsDFMe, S=10, R=20, A=sh -c $u S10 R@ MAILER-DAEMON errors to mailer-daemon CF_HIDDENHOSTSR$+<@$+.$j>$* $1<@$j>$3 hide anydom.$j under $j S20 ############################################################ # # UUCP Mailer specification # ############################################################ Muux, P=/bin/smail, F=sDFMhum, S=14, R=24, M=100000, A=smail -vH$j $h!$u S14 R$+<@$=E> $1 user@etherhost -> user R$*<@$+>$* $@$1<@$2>$3 already ok CF_HIDDENHOSTSR$+<@$+.$j>$* $1<@$j>$3 hide anydom.$j under $j R$+ $@$1<@$j> add our full address S24 ############################################################ # # SMTP ethernet mailer # ############################################################ Mether, P=[IPC], F=msDFMuCXP, S=11, R=21, A=IPC $h S11 R$*<@$+>$* $@$1<@$2>$3 already ok R$+ $@$1<@$w> add our hostname S21 ################################# # Final Output Post-rewriting # ################################# # This rewrites the internal $=T mock domains into their external form. # The default is to replace the mock domain name with $D. # The last two lines are stock. S4 R@ $@ handle <> error addr R$+<@$-.UUX> $2!$1 u@host.UUX => host!u R$*<$*$=T>$* $:$1<$2$D>$4 change local info R$*<$+>$* $1$2$3 defocus R@$+:$+:$+ @$1,$2:$3 <route-addr> canonical //E*O*F template.cf// exit 0