1292Seric # include <stdio.h> 2292Seric # include <ctype.h> 3292Seric # include <pwd.h> 4292Seric # include "dlvrmail.h" 5292Seric 6*1874Seric static char SccsId[] = "@(#)alias.c 2.2 12/06/80"; 7402Seric 8292Seric /* 9292Seric ** ALIAS -- Compute aliases. 10292Seric ** 111503Smark ** Scans the file ALIASFILE for a set of aliases. 12292Seric ** If found, it arranges to deliver to them by inserting the 131503Smark ** 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 ** 29292Seric ** Called By: 30292Seric ** main 31292Seric ** 32292Seric ** Files: 33569Seric ** ALIASFILE -- the mail aliases. The format is 34569Seric ** a series of lines of the form: 35569Seric ** alias:name1,name2,name3,... 36569Seric ** where 'alias' expands to all of 37569Seric ** 'name[i]'. Continuations begin with 38569Seric ** space or tab. 391503Smark ** ALIASFILE.pag, ALIASFILE.dir: libdbm version 401503Smark ** of alias file. Keys are aliases, datums 411503Smark ** (data?) are name1,name2, ... 42292Seric ** 43292Seric ** Notes: 44292Seric ** If NoAlias (the "-n" flag) is set, no aliasing is 45292Seric ** done. 46292Seric ** 47292Seric ** Deficiencies: 48292Seric ** It should complain about names that are aliased to 49292Seric ** nothing. 50292Seric ** It is unsophisticated about line overflows. 51292Seric */ 52292Seric 53292Seric 54292Seric # define MAXRCRSN 10 55292Seric 561503Smark #ifdef DBM 571503Smark typedef struct {char *dptr; int dsize;} datum; 581503Smark datum lhs, rhs; 591515Seric extern datum fetch(); 601503Smark #endif DBM 61292Seric 62292Seric alias() 63292Seric { 64292Seric register addrq *q; 651622Seric addrq *q2; 66292Seric FILE *af; 67292Seric char line[MAXLINE+1]; 68292Seric register char *p; 69292Seric extern int errno; 70292Seric bool didalias; 71292Seric bool gotmatch; 72292Seric auto addrq al; 73292Seric extern bool sameaddr(); 74292Seric extern addrq *parse(); 75292Seric 76292Seric if (NoAlias) 77292Seric return; 78292Seric # ifdef DEBUG 79292Seric if (Debug) 80292Seric printf("--- alias ---\n"); 81292Seric # endif 82292Seric 83292Seric /* open alias file if not already open */ 841503Smark #ifndef DBM 85292Seric # ifdef DEBUG 86292Seric if (Debug && (af = fopen("mailaliases", "r")) != NULL) 87292Seric printf(" [using local alias file]\n"); 88292Seric else 89292Seric # endif 90292Seric if ((af = fopen(ALIASFILE, "r")) == NULL) 91292Seric { 92292Seric # ifdef DEBUG 93292Seric if (Debug) 94292Seric printf("Can't open %s\n", ALIASFILE); 95292Seric # endif 96292Seric errno = 0; 97292Seric return; 98292Seric } 991503Smark #else DBM 1001503Smark dbminit(ALIASFILE); 1011503Smark #endif DBM 102292Seric 1031503Smark #ifndef DBM 104292Seric /* 105292Seric ** Scan alias file. 106292Seric ** If we find any user that any line matches any user, we 107292Seric ** will send to the line rather than to the user. 108292Seric ** 109292Seric ** We pass through the file several times. Didalias tells 110292Seric ** us if we took some alias on this pass through the file; 111292Seric ** when it goes false at the top of the loop we don't have 112292Seric ** to scan any more. Gotmatch tells the same thing, but 113292Seric ** on a line-by-line basis; it is used for processing 114292Seric ** continuation lines. 115292Seric */ 116292Seric 1171503Smark do 118292Seric { 119292Seric didalias = FALSE; 120292Seric gotmatch = FALSE; 121292Seric rewind(af); 122292Seric while (fgets(line, sizeof line, af) != NULL) 123292Seric { 124292Seric /* comments begin with `#' */ 125292Seric if (line[0] == '#') 126292Seric continue; 127292Seric 128292Seric /* check for continuation lines */ 129292Seric if (isspace(line[0])) 130292Seric { 131292Seric if (gotmatch) 132292Seric { 133292Seric sendto(line, 1); 134292Seric } 135292Seric continue; 136292Seric } 137292Seric gotmatch = FALSE; 138292Seric 139292Seric /* 140292Seric ** Check to see if this pseudonym exists in SendQ. 141292Seric ** Turn the alias into canonical form. 142292Seric ** Then scan SendQ until you do (or do not) 143292Seric ** find that address. 144292Seric */ 145292Seric 146292Seric /* Get a canonical form for the alias. */ 147292Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 148292Seric continue; 149292Seric if (*p == '\0' || *p == '\n') 150292Seric { 151292Seric syntaxerr: 152292Seric syserr("Bad alias line `%s'", line); 153292Seric continue; 154292Seric } 155292Seric *p++ = '\0'; 156292Seric if (parse(line, &al, -1) == NULL) 157292Seric { 158292Seric *--p = ':'; 159292Seric goto syntaxerr; 160292Seric } 161292Seric 162*1874Seric /* if already in AliasQ don't realias */ 163*1874Seric for (q = &AliasQ; (q = nxtinq(q)) != NULL; ) 164*1874Seric { 165*1874Seric if (sameaddr(&al, q, TRUE)) 166*1874Seric break; 167*1874Seric } 168*1874Seric if (q != NULL) 169*1874Seric continue; 170*1874Seric 171292Seric /* Scan SendQ for that canonical form. */ 172292Seric for (q = &SendQ; (q = nxtinq(q)) != NULL; ) 173292Seric { 174292Seric if (sameaddr(&al, q, TRUE)) 175292Seric break; 176292Seric } 177292Seric if (q != NULL) 178292Seric { 179292Seric /* 180292Seric ** Match on Alias. 181292Seric ** Deliver to the target list. 182292Seric ** Remove the alias from the send queue 183292Seric ** and put it on the Alias queue. 184292Seric */ 185292Seric 186292Seric # ifdef DEBUG 187292Seric if (Debug) 188292Seric printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n", 189292Seric q->q_paddr, q->q_host, q->q_user, 190292Seric p, al.q_paddr, al.q_host, al.q_user); 191292Seric # endif 192292Seric tkoffq(q, &SendQ); 193292Seric didalias++; 194292Seric gotmatch++; 195292Seric sendto(p, 1); 196*1874Seric putonq(q, &AliasQ); 197292Seric } 198292Seric } 1991503Smark } while (didalias); 200292Seric fclose(af); 2011515Seric #else DBM 2021515Seric /* 2031515Seric ** Scan SendQ 2041515Seric ** We only have to do this once, since anything we alias 205*1874Seric ** to is being put at the end of the queue we are 2061515Seric ** scanning. 207*1874Seric ** If the alias on SendQ is also (already) on AliasQ, we 208*1874Seric ** have an alias such as: 209*1874Seric ** eric:eric,i:eric 210*1874Seric ** In this case we have already done this alias once, and 211*1874Seric ** we don't want to do it again (for obvious reasons!). 2121515Seric */ 2131515Seric 214*1874Seric for (q2 = nxtinq(&SendQ); q2 != NULL; ) 2151515Seric { 216*1874Seric /* if already in AliasQ, don't realias */ 217*1874Seric for (q = &AliasQ; (q = nxtinq(q)) != NULL; ) 218*1874Seric { 219*1874Seric if (sameaddr(q, q2, TRUE)) 220*1874Seric break; 221*1874Seric } 222*1874Seric if (q != NULL) 223*1874Seric { 224*1874Seric q2 = nxtinq(q2); 225*1874Seric continue; 226*1874Seric } 227*1874Seric 2281622Seric /* save ptr to next address */ 229*1874Seric q = q2; 2301622Seric q2 = nxtinq(q); 2311622Seric 2321515Seric /* only alias local users */ 2331515Seric if (q->q_mailer != &Mailer[0]) 2341515Seric continue; 2351515Seric 2361515Seric /* create a key for fetch */ 2371515Seric lhs.dptr = q->q_user; 2381515Seric lhs.dsize = strlen(q->q_user) + 1; 2391515Seric rhs = fetch(lhs); 2401515Seric 2411515Seric /* find this alias? */ 2421515Seric p = rhs.dptr; 2431515Seric if (p == NULL) 2441515Seric continue; 2451515Seric 2461515Seric /* 2471515Seric ** Match on Alias. 2481515Seric ** Deliver to the target list. 2491515Seric ** Remove the alias from the send queue 2501515Seric ** and put it on the Alias queue. 2511515Seric */ 2521515Seric 2531515Seric # ifdef DEBUG 2541515Seric if (Debug) 2551515Seric printf("%s (%s, %s) aliased to %s\n", 2561515Seric q->q_paddr, q->q_host, q->q_user, p); 2571515Seric # endif 2581515Seric tkoffq(q, &SendQ); 259*1874Seric sendto(p, 1); 2601515Seric putonq(q, &AliasQ); 2611633Seric 2621633Seric /* if our last entry had an alias, process them */ 2631633Seric if (q2 == NULL) 2641633Seric q2 = nxtinq(&SendQ); 2651515Seric } 2661515Seric #endif DBM 267292Seric } 268292Seric /* 269292Seric ** FORWARD -- Try to forward mail 270292Seric ** 271292Seric ** This is similar but not identical to aliasing. 272292Seric ** 273292Seric ** Currently it is undefined, until the protocol for userinfo 274292Seric ** databases is finalized. 275292Seric ** 276292Seric ** Parameters: 277292Seric ** user -- the name of the user who's mail we 278292Seric ** would like to forward to. 279292Seric ** 280292Seric ** Returns: 281292Seric ** TRUE -- we have forwarded it somewhere. 282292Seric ** FALSE -- not forwarded; go ahead & deliver. 283292Seric ** 284292Seric ** Side Effects: 285292Seric ** New names are added to SendQ. 286292Seric ** 287292Seric ** Called By: 288292Seric ** recipient 289292Seric */ 290292Seric 291292Seric bool 292292Seric forward(user) 293292Seric addrq *user; 294292Seric { 295292Seric return (FALSE); 296292Seric } 297