1292Seric # include <stdio.h> 2292Seric # include <ctype.h> 3292Seric # include <pwd.h> 4*2966Seric # include "postbox.h" 5292Seric 6*2966Seric static char SccsId[] = "@(#)alias.c 3.1 03/07/81"; 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 57*2966Seric typedef struct 58*2966Seric { 59*2966Seric char *dptr; 60*2966Seric int dsize; 61*2966Seric } datum; 621503Smark datum lhs, rhs; 631515Seric extern datum fetch(); 641503Smark #endif DBM 65292Seric 66292Seric alias() 67292Seric { 68*2966Seric register ADDRESS *q; 69*2966Seric ADDRESS *q2; 70292Seric FILE *af; 71292Seric char line[MAXLINE+1]; 72292Seric register char *p; 73292Seric extern int errno; 74292Seric bool didalias; 75292Seric bool gotmatch; 76*2966Seric auto ADDRESS al; 77292Seric extern bool sameaddr(); 78*2966Seric extern ADDRESS *parse(); 79292Seric 80292Seric if (NoAlias) 81292Seric return; 82292Seric # ifdef DEBUG 83292Seric if (Debug) 84292Seric printf("--- alias ---\n"); 85292Seric # endif 86292Seric 87292Seric /* open alias file if not already open */ 881503Smark #ifndef DBM 89292Seric # ifdef DEBUG 90292Seric if (Debug && (af = fopen("mailaliases", "r")) != NULL) 91292Seric printf(" [using local alias file]\n"); 92292Seric else 93292Seric # endif 94292Seric if ((af = fopen(ALIASFILE, "r")) == NULL) 95292Seric { 96292Seric # ifdef DEBUG 97292Seric if (Debug) 98292Seric printf("Can't open %s\n", ALIASFILE); 99292Seric # endif 100292Seric errno = 0; 101292Seric return; 102292Seric } 1031503Smark #else DBM 1041503Smark dbminit(ALIASFILE); 1051503Smark #endif DBM 106292Seric 1071503Smark #ifndef DBM 108292Seric /* 109292Seric ** Scan alias file. 110292Seric ** If we find any user that any line matches any user, we 111292Seric ** will send to the line rather than to the user. 112292Seric ** 113292Seric ** We pass through the file several times. Didalias tells 114292Seric ** us if we took some alias on this pass through the file; 115292Seric ** when it goes false at the top of the loop we don't have 116292Seric ** to scan any more. Gotmatch tells the same thing, but 117292Seric ** on a line-by-line basis; it is used for processing 118292Seric ** continuation lines. 119292Seric */ 120292Seric 1211503Smark do 122292Seric { 123292Seric didalias = FALSE; 124292Seric gotmatch = FALSE; 125292Seric rewind(af); 126292Seric while (fgets(line, sizeof line, af) != NULL) 127292Seric { 128292Seric /* comments begin with `#' */ 129292Seric if (line[0] == '#') 130292Seric continue; 131292Seric 132292Seric /* check for continuation lines */ 133292Seric if (isspace(line[0])) 134292Seric { 135292Seric if (gotmatch) 136292Seric { 137292Seric sendto(line, 1); 138292Seric } 139292Seric continue; 140292Seric } 141292Seric gotmatch = FALSE; 142292Seric 143292Seric /* 144292Seric ** Check to see if this pseudonym exists in SendQ. 145292Seric ** Turn the alias into canonical form. 146292Seric ** Then scan SendQ until you do (or do not) 147292Seric ** find that address. 148292Seric */ 149292Seric 150292Seric /* Get a canonical form for the alias. */ 151292Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 152292Seric continue; 153292Seric if (*p == '\0' || *p == '\n') 154292Seric { 155292Seric syntaxerr: 156292Seric syserr("Bad alias line `%s'", line); 157292Seric continue; 158292Seric } 159292Seric *p++ = '\0'; 160292Seric if (parse(line, &al, -1) == NULL) 161292Seric { 162292Seric *--p = ':'; 163292Seric goto syntaxerr; 164292Seric } 165292Seric 1661874Seric /* if already in AliasQ don't realias */ 1671874Seric for (q = &AliasQ; (q = nxtinq(q)) != NULL; ) 1681874Seric { 1691874Seric if (sameaddr(&al, q, TRUE)) 1701874Seric break; 1711874Seric } 1721874Seric if (q != NULL) 1731874Seric continue; 1741874Seric 175292Seric /* Scan SendQ for that canonical form. */ 176292Seric for (q = &SendQ; (q = nxtinq(q)) != NULL; ) 177292Seric { 178292Seric if (sameaddr(&al, q, TRUE)) 179292Seric break; 180292Seric } 181292Seric if (q != NULL) 182292Seric { 183292Seric /* 184292Seric ** Match on Alias. 185292Seric ** Deliver to the target list. 186292Seric ** Remove the alias from the send queue 187292Seric ** and put it on the Alias queue. 188292Seric */ 189292Seric 190292Seric # ifdef DEBUG 191292Seric if (Debug) 192292Seric printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n", 193292Seric q->q_paddr, q->q_host, q->q_user, 194292Seric p, al.q_paddr, al.q_host, al.q_user); 195292Seric # endif 196292Seric tkoffq(q, &SendQ); 197292Seric didalias++; 198292Seric gotmatch++; 199292Seric sendto(p, 1); 2001874Seric putonq(q, &AliasQ); 201292Seric } 202292Seric } 2031503Smark } while (didalias); 204292Seric fclose(af); 2051515Seric #else DBM 2061515Seric /* 2071515Seric ** Scan SendQ 2081515Seric ** We only have to do this once, since anything we alias 2091874Seric ** to is being put at the end of the queue we are 2101515Seric ** scanning. 2111874Seric ** If the alias on SendQ is also (already) on AliasQ, we 2121874Seric ** have an alias such as: 2131874Seric ** eric:eric,i:eric 2141874Seric ** In this case we have already done this alias once, and 2151874Seric ** we don't want to do it again (for obvious reasons!). 2161515Seric */ 2171515Seric 2181874Seric for (q2 = nxtinq(&SendQ); q2 != NULL; ) 2191515Seric { 2201874Seric /* if already in AliasQ, don't realias */ 2211874Seric for (q = &AliasQ; (q = nxtinq(q)) != NULL; ) 2221874Seric { 2231874Seric if (sameaddr(q, q2, TRUE)) 2241874Seric break; 2251874Seric } 2261874Seric if (q != NULL) 2271874Seric { 2281874Seric q2 = nxtinq(q2); 2291874Seric continue; 2301874Seric } 2311874Seric 2321622Seric /* save ptr to next address */ 2331874Seric q = q2; 2341622Seric q2 = nxtinq(q); 2351622Seric 2361515Seric /* only alias local users */ 2371515Seric if (q->q_mailer != &Mailer[0]) 2381515Seric continue; 2391515Seric 2401515Seric /* create a key for fetch */ 2411515Seric lhs.dptr = q->q_user; 2421515Seric lhs.dsize = strlen(q->q_user) + 1; 2431515Seric rhs = fetch(lhs); 2441515Seric 2451515Seric /* find this alias? */ 2461515Seric p = rhs.dptr; 2471515Seric if (p == NULL) 2481515Seric continue; 2491515Seric 2501515Seric /* 2511515Seric ** Match on Alias. 2521515Seric ** Deliver to the target list. 2531515Seric ** Remove the alias from the send queue 2541515Seric ** and put it on the Alias queue. 2551515Seric */ 2561515Seric 2571515Seric # ifdef DEBUG 2581515Seric if (Debug) 2591515Seric printf("%s (%s, %s) aliased to %s\n", 2601515Seric q->q_paddr, q->q_host, q->q_user, p); 2611515Seric # endif 2621515Seric tkoffq(q, &SendQ); 2631874Seric sendto(p, 1); 2641515Seric putonq(q, &AliasQ); 2651633Seric 2661633Seric /* if our last entry had an alias, process them */ 2671633Seric if (q2 == NULL) 2681633Seric q2 = nxtinq(&SendQ); 2691515Seric } 2701515Seric #endif DBM 271292Seric } 272292Seric /* 273292Seric ** FORWARD -- Try to forward mail 274292Seric ** 275292Seric ** This is similar but not identical to aliasing. 276292Seric ** 277292Seric ** Currently it is undefined, until the protocol for userinfo 278292Seric ** databases is finalized. 279292Seric ** 280292Seric ** Parameters: 281292Seric ** user -- the name of the user who's mail we 282292Seric ** would like to forward to. 283292Seric ** 284292Seric ** Returns: 285292Seric ** TRUE -- we have forwarded it somewhere. 286292Seric ** FALSE -- not forwarded; go ahead & deliver. 287292Seric ** 288292Seric ** Side Effects: 289292Seric ** New names are added to SendQ. 290292Seric ** 291292Seric ** Called By: 292292Seric ** recipient 293292Seric */ 294292Seric 295292Seric bool 296292Seric forward(user) 297*2966Seric ADDRESS *user; 298292Seric { 299292Seric return (FALSE); 300292Seric } 301