1292Seric # include <stdio.h> 2292Seric # include <ctype.h> 3292Seric # include <pwd.h> 4292Seric # include "dlvrmail.h" 5292Seric 6*1503Smark static char SccsId[] = "@(#)alias.c 1.4 10/17/80"; 7402Seric 8292Seric /* 9292Seric ** ALIAS -- Compute aliases. 10292Seric ** 11*1503Smark ** Scans the file ALIASFILE for a set of aliases. 12292Seric ** If found, it arranges to deliver to them by inserting the 13*1503Smark ** new names onto the SendQ queue. Uses libdbm database if -DDBM. 14292Seric ** 15292Seric ** Parameters: 16292Seric ** none 17292Seric ** 18292Seric ** Returns: 19292Seric ** none 20292Seric ** 21292Seric ** Side Effects: 22292Seric ** Aliases found on SendQ are removed and put onto 23292Seric ** AliasQ; replacements are added to SendQ. This is 24292Seric ** done until no such replacement occurs. 25292Seric ** 26292Seric ** Defined Constants: 27292Seric ** MAXRCRSN -- the maximum recursion depth. 28292Seric ** ALIASFILE -- the pathname of the alias file. 29292Seric ** 30292Seric ** Called By: 31292Seric ** main 32292Seric ** 33292Seric ** Files: 34569Seric ** ALIASFILE -- the mail aliases. The format is 35569Seric ** a series of lines of the form: 36569Seric ** alias:name1,name2,name3,... 37569Seric ** where 'alias' expands to all of 38569Seric ** 'name[i]'. Continuations begin with 39569Seric ** space or tab. 40*1503Smark ** ALIASFILE.pag, ALIASFILE.dir: libdbm version 41*1503Smark ** of alias file. Keys are aliases, datums 42*1503Smark ** (data?) are name1,name2, ... 43292Seric ** 44292Seric ** Notes: 45292Seric ** If NoAlias (the "-n" flag) is set, no aliasing is 46292Seric ** done. 47292Seric ** 48292Seric ** Deficiencies: 49292Seric ** It should complain about names that are aliased to 50292Seric ** nothing. 51292Seric ** It is unsophisticated about line overflows. 52292Seric */ 53292Seric 54292Seric 55292Seric # define ALIASFILE "/usr/lib/mailaliases" 56292Seric # define MAXRCRSN 10 57292Seric 58*1503Smark #ifdef DBM 59*1503Smark typedef struct {char *dptr; int dsize;} datum; 60*1503Smark datum lhs, rhs; 61*1503Smark datum fetch(); 62*1503Smark #endif DBM 63292Seric 64292Seric alias() 65292Seric { 66292Seric register addrq *q; 67292Seric FILE *af; 68292Seric char line[MAXLINE+1]; 69292Seric register char *p; 70292Seric extern int errno; 71292Seric bool didalias; 72292Seric bool gotmatch; 73292Seric auto addrq al; 74292Seric extern bool sameaddr(); 75292Seric extern addrq *parse(); 76292Seric 77292Seric if (NoAlias) 78292Seric return; 79292Seric # ifdef DEBUG 80292Seric if (Debug) 81292Seric printf("--- alias ---\n"); 82292Seric # endif 83292Seric 84292Seric /* open alias file if not already open */ 85*1503Smark #ifndef DBM 86292Seric # ifdef DEBUG 87292Seric if (Debug && (af = fopen("mailaliases", "r")) != NULL) 88292Seric printf(" [using local alias file]\n"); 89292Seric else 90292Seric # endif 91292Seric if ((af = fopen(ALIASFILE, "r")) == NULL) 92292Seric { 93292Seric # ifdef DEBUG 94292Seric if (Debug) 95292Seric printf("Can't open %s\n", ALIASFILE); 96292Seric # endif 97292Seric errno = 0; 98292Seric return; 99292Seric } 100*1503Smark #else DBM 101*1503Smark dbminit(ALIASFILE); 102*1503Smark #endif DBM 103292Seric 104*1503Smark #ifndef DBM 105292Seric /* 106292Seric ** Scan alias file. 107292Seric ** If we find any user that any line matches any user, we 108292Seric ** will send to the line rather than to the user. 109292Seric ** 110292Seric ** We pass through the file several times. Didalias tells 111292Seric ** us if we took some alias on this pass through the file; 112292Seric ** when it goes false at the top of the loop we don't have 113292Seric ** to scan any more. Gotmatch tells the same thing, but 114292Seric ** on a line-by-line basis; it is used for processing 115292Seric ** continuation lines. 116292Seric */ 117292Seric 118*1503Smark do 119292Seric { 120292Seric didalias = FALSE; 121292Seric gotmatch = FALSE; 122292Seric rewind(af); 123292Seric while (fgets(line, sizeof line, af) != NULL) 124292Seric { 125292Seric /* comments begin with `#' */ 126292Seric if (line[0] == '#') 127292Seric continue; 128292Seric 129292Seric /* check for continuation lines */ 130292Seric if (isspace(line[0])) 131292Seric { 132292Seric if (gotmatch) 133292Seric { 134292Seric sendto(line, 1); 135292Seric } 136292Seric continue; 137292Seric } 138292Seric gotmatch = FALSE; 139292Seric 140292Seric /* 141292Seric ** Check to see if this pseudonym exists in SendQ. 142292Seric ** Turn the alias into canonical form. 143292Seric ** Then scan SendQ until you do (or do not) 144292Seric ** find that address. 145292Seric */ 146292Seric 147292Seric /* Get a canonical form for the alias. */ 148292Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 149292Seric continue; 150292Seric if (*p == '\0' || *p == '\n') 151292Seric { 152292Seric syntaxerr: 153292Seric syserr("Bad alias line `%s'", line); 154292Seric continue; 155292Seric } 156292Seric *p++ = '\0'; 157292Seric if (parse(line, &al, -1) == NULL) 158292Seric { 159292Seric *--p = ':'; 160292Seric goto syntaxerr; 161292Seric } 162292Seric 163292Seric /* Scan SendQ for that canonical form. */ 164292Seric for (q = &SendQ; (q = nxtinq(q)) != NULL; ) 165292Seric { 166292Seric if (sameaddr(&al, q, TRUE)) 167292Seric break; 168292Seric } 169292Seric if (q != NULL) 170292Seric { 171*1503Smark #else DBM 172*1503Smark /* 173*1503Smark ** Scan SendQ 174*1503Smark ** We pass through the queue several times. Didalias tells 175*1503Smark ** us if we took some alias on this pass through the queue; 176*1503Smark ** when it goes false at the top of the loop we don't have 177*1503Smark ** to scan any more. 178*1503Smark */ 179*1503Smark 180*1503Smark do 181*1503Smark { 182*1503Smark didalias = FALSE; 183*1503Smark /* Scan SendQ for that canonical form. */ 184*1503Smark for (q = &SendQ; (q = nxtinq(q)) != NULL; ) 185*1503Smark { 186*1503Smark lhs.dptr = q -> q_paddr; 187*1503Smark lhs.dsize = strlen(lhs.dptr)+1; 188*1503Smark rhs = fetch(lhs); 189*1503Smark p = rhs.dptr; 190*1503Smark if (p != NULL) 191*1503Smark { 192*1503Smark #endif 193292Seric /* 194292Seric ** Match on Alias. 195292Seric ** Deliver to the target list. 196292Seric ** Remove the alias from the send queue 197292Seric ** and put it on the Alias queue. 198292Seric */ 199292Seric 200292Seric # ifdef DEBUG 201292Seric if (Debug) 202292Seric printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n", 203292Seric q->q_paddr, q->q_host, q->q_user, 204292Seric p, al.q_paddr, al.q_host, al.q_user); 205292Seric # endif 206292Seric tkoffq(q, &SendQ); 207292Seric putonq(q, &AliasQ); 208292Seric didalias++; 209292Seric gotmatch++; 210292Seric sendto(p, 1); 211292Seric } 212292Seric } 213*1503Smark } while (didalias); 214*1503Smark #ifndef DBM 215292Seric fclose(af); 216*1503Smark #endif 217292Seric } 218292Seric /* 219292Seric ** FORWARD -- Try to forward mail 220292Seric ** 221292Seric ** This is similar but not identical to aliasing. 222292Seric ** 223292Seric ** Currently it is undefined, until the protocol for userinfo 224292Seric ** databases is finalized. 225292Seric ** 226292Seric ** Parameters: 227292Seric ** user -- the name of the user who's mail we 228292Seric ** would like to forward to. 229292Seric ** 230292Seric ** Returns: 231292Seric ** TRUE -- we have forwarded it somewhere. 232292Seric ** FALSE -- not forwarded; go ahead & deliver. 233292Seric ** 234292Seric ** Side Effects: 235292Seric ** New names are added to SendQ. 236292Seric ** 237292Seric ** Called By: 238292Seric ** recipient 239292Seric */ 240292Seric 241292Seric bool 242292Seric forward(user) 243292Seric addrq *user; 244292Seric { 245292Seric return (FALSE); 246292Seric } 247