1292Seric # include <stdio.h> 2292Seric # include <ctype.h> 3292Seric # include <pwd.h> 4*3309Seric # include "sendmail.h" 5292Seric 6*3309Seric static char SccsId[] = "@(#)alias.c 3.4 03/20/81"; 7402Seric 8292Seric /* 9292Seric ** ALIAS -- Compute aliases. 10292Seric ** 111503Smark ** Scans the file ALIASFILE for a set of aliases. 123185Seric ** If found, it arranges to deliver to them. Uses libdbm 133185Seric ** database if -DDBM. 14292Seric ** 15292Seric ** Parameters: 16292Seric ** none 17292Seric ** 18292Seric ** Returns: 19292Seric ** none 20292Seric ** 21292Seric ** Side Effects: 223185Seric ** Aliases found are expanded. 23292Seric ** 24292Seric ** Defined Constants: 25292Seric ** MAXRCRSN -- the maximum recursion depth. 26292Seric ** 27292Seric ** Files: 28569Seric ** ALIASFILE -- the mail aliases. The format is 29569Seric ** a series of lines of the form: 30569Seric ** alias:name1,name2,name3,... 31569Seric ** where 'alias' expands to all of 32569Seric ** 'name[i]'. Continuations begin with 33569Seric ** space or tab. 341503Smark ** ALIASFILE.pag, ALIASFILE.dir: libdbm version 351503Smark ** of alias file. Keys are aliases, datums 361503Smark ** (data?) are name1,name2, ... 37292Seric ** 38292Seric ** Notes: 39292Seric ** If NoAlias (the "-n" flag) is set, no aliasing is 40292Seric ** done. 41292Seric ** 42292Seric ** Deficiencies: 43292Seric ** It should complain about names that are aliased to 44292Seric ** nothing. 45292Seric ** It is unsophisticated about line overflows. 46292Seric */ 47292Seric 48292Seric 49292Seric # define MAXRCRSN 10 50292Seric 511503Smark #ifdef DBM 522966Seric typedef struct 532966Seric { 542966Seric char *dptr; 552966Seric int dsize; 562966Seric } datum; 571503Smark datum lhs, rhs; 581515Seric extern datum fetch(); 591503Smark #endif DBM 60292Seric 61292Seric alias() 62292Seric { 632966Seric register ADDRESS *q; 642966Seric ADDRESS *q2; 65292Seric FILE *af; 66292Seric char line[MAXLINE+1]; 67292Seric register char *p; 68292Seric extern int errno; 69292Seric bool didalias; 70292Seric bool gotmatch; 712966Seric auto ADDRESS al; 72292Seric extern bool sameaddr(); 732966Seric extern ADDRESS *parse(); 743185Seric int mno; 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 /* 1403185Seric ** Check to see if this pseudonym exists. 141292Seric ** Turn the alias into canonical form. 1423185Seric ** Then scan the send queue until you 1433185Seric ** do (or do not) 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 1623185Seric /* if already queued up, don't realias */ 1633185Seric for (q = Mailer[al.q_mailer]->m_sendq; q != NULL; q = q->q_next) 1641874Seric { 1651874Seric if (sameaddr(&al, q, TRUE)) 1661874Seric break; 1671874Seric } 1683185Seric if (q == NULL || bitset(QDONTSEND, q->q_flags)) 1691874Seric continue; 1701874Seric 1713185Seric /* 1723185Seric ** Match on Alias. 1733185Seric ** Deliver to the target list. 1743185Seric ** Remove the alias from the send queue 1753185Seric ** and put it on the Alias queue. 1763185Seric */ 177292Seric 178292Seric # ifdef DEBUG 1793185Seric if (Debug) 1803185Seric printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n", 1813185Seric q->q_paddr, q->q_host, q->q_user, 1823185Seric p, al.q_paddr, al.q_host, al.q_user); 183292Seric # endif 1843185Seric q->q_flags |= QDONTSEND; 1853185Seric didalias++; 1863185Seric gotmatch++; 1873185Seric sendto(p, 1); 188292Seric } 1891503Smark } while (didalias); 190292Seric fclose(af); 1911515Seric #else DBM 1921515Seric /* 1933185Seric ** Scan send queues 1941515Seric ** We only have to do this once, since anything we alias 1951874Seric ** to is being put at the end of the queue we are 1961515Seric ** scanning. 1971515Seric */ 1981515Seric 1993185Seric for (mno = 0; Mailer[mno] != NULL; mno++) 2001515Seric { 2013185Seric for (q = Mailer[mno]->m_sendq; q != NULL; q = q->q_next) 2021874Seric { 2033185Seric /* don't realias already aliased names */ 2043185Seric if (bitset(QDONTSEND, q->q_flags)) 2053185Seric continue; 2061874Seric 2073185Seric /* only alias local users */ 2083185Seric if (q->q_mailer != 0) 2093185Seric continue; 2101622Seric 2113185Seric /* create a key for fetch */ 2123185Seric lhs.dptr = q->q_user; 2133185Seric lhs.dsize = strlen(q->q_user) + 1; 2143185Seric rhs = fetch(lhs); 2151515Seric 2163185Seric /* find this alias? */ 2173185Seric p = rhs.dptr; 2183185Seric if (p == NULL) 2193185Seric continue; 2201515Seric 2213185Seric /* 2223185Seric ** Match on Alias. 2233185Seric ** Deliver to the target list. 2243185Seric ** Remove the alias from the send queue 2253185Seric ** and put it on the Alias queue. 2263185Seric */ 2271515Seric 2281515Seric # ifdef DEBUG 2293185Seric if (Debug) 2303185Seric printf("%s (%s, %s) aliased to %s\n", 2313185Seric q->q_paddr, q->q_host, q->q_user, p); 2321515Seric # endif 2333185Seric q->q_flags |= QDONTSEND; 2343185Seric sendto(p, 1); 2353185Seric } 2361515Seric } 2371515Seric #endif DBM 238292Seric } 239292Seric /* 240292Seric ** FORWARD -- Try to forward mail 241292Seric ** 242292Seric ** This is similar but not identical to aliasing. 243292Seric ** 244292Seric ** Currently it is undefined, until the protocol for userinfo 245292Seric ** databases is finalized. 246292Seric ** 247292Seric ** Parameters: 248292Seric ** user -- the name of the user who's mail we 249292Seric ** would like to forward to. 250292Seric ** 251292Seric ** Returns: 252292Seric ** TRUE -- we have forwarded it somewhere. 253292Seric ** FALSE -- not forwarded; go ahead & deliver. 254292Seric ** 255292Seric ** Side Effects: 2563185Seric ** New names are added to send queues. 257292Seric */ 258292Seric 259292Seric bool 260292Seric forward(user) 2612966Seric ADDRESS *user; 262292Seric { 263292Seric return (FALSE); 264292Seric } 265