1292Seric # include <stdio.h> 2292Seric # include <ctype.h> 3292Seric # include <pwd.h> 43309Seric # include "sendmail.h" 5292Seric 6*4081Seric static char SccsId[] = "@(#)alias.c 3.8 08/09/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; 64*4081Seric register char *p; 65*4081Seric # ifndef DBM 66292Seric FILE *af; 67292Seric char line[MAXLINE+1]; 68292Seric bool didalias; 69292Seric bool gotmatch; 702966Seric auto ADDRESS al; 71*4081Seric # else 723185Seric int mno; 73*4081Seric # endif DBM 74292Seric 75292Seric if (NoAlias) 76292Seric return; 77292Seric # ifdef DEBUG 78292Seric if (Debug) 79292Seric printf("--- alias ---\n"); 80292Seric # endif 81292Seric 82292Seric /* open alias file if not already open */ 831503Smark #ifndef DBM 84292Seric # ifdef DEBUG 85292Seric if (Debug && (af = fopen("mailaliases", "r")) != NULL) 86292Seric printf(" [using local alias file]\n"); 87292Seric else 88292Seric # endif 89292Seric if ((af = fopen(ALIASFILE, "r")) == NULL) 90292Seric { 91292Seric # ifdef DEBUG 92292Seric if (Debug) 93292Seric printf("Can't open %s\n", ALIASFILE); 94292Seric # endif 95292Seric errno = 0; 96292Seric return; 97292Seric } 981503Smark #else DBM 991503Smark dbminit(ALIASFILE); 1001503Smark #endif DBM 101292Seric 1021503Smark #ifndef DBM 103292Seric /* 104292Seric ** Scan alias file. 105292Seric ** If we find any user that any line matches any user, we 106292Seric ** will send to the line rather than to the user. 107292Seric ** 108292Seric ** We pass through the file several times. Didalias tells 109292Seric ** us if we took some alias on this pass through the file; 110292Seric ** when it goes false at the top of the loop we don't have 111292Seric ** to scan any more. Gotmatch tells the same thing, but 112292Seric ** on a line-by-line basis; it is used for processing 113292Seric ** continuation lines. 114292Seric */ 115292Seric 1161503Smark do 117292Seric { 118292Seric didalias = FALSE; 119292Seric gotmatch = FALSE; 120292Seric rewind(af); 121292Seric while (fgets(line, sizeof line, af) != NULL) 122292Seric { 123292Seric /* comments begin with `#' */ 124292Seric if (line[0] == '#') 125292Seric continue; 126292Seric 127292Seric /* check for continuation lines */ 128292Seric if (isspace(line[0])) 129292Seric { 130292Seric if (gotmatch) 131292Seric { 132292Seric sendto(line, 1); 133292Seric } 134292Seric continue; 135292Seric } 136292Seric gotmatch = FALSE; 137292Seric 138292Seric /* 1393185Seric ** Check to see if this pseudonym exists. 140292Seric ** Turn the alias into canonical form. 1413185Seric ** Then scan the send queue until you 1423185Seric ** do (or do not) find that address. 143292Seric */ 144292Seric 145292Seric /* Get a canonical form for the alias. */ 146292Seric for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 147292Seric continue; 148292Seric if (*p == '\0' || *p == '\n') 149292Seric { 150292Seric syntaxerr: 151292Seric syserr("Bad alias line `%s'", line); 152292Seric continue; 153292Seric } 154292Seric *p++ = '\0'; 155292Seric if (parse(line, &al, -1) == NULL) 156292Seric { 157292Seric *--p = ':'; 158292Seric goto syntaxerr; 159292Seric } 160292Seric 1613185Seric /* if already queued up, don't realias */ 1623185Seric for (q = Mailer[al.q_mailer]->m_sendq; q != NULL; q = q->q_next) 1631874Seric { 1641874Seric if (sameaddr(&al, q, TRUE)) 1651874Seric break; 1661874Seric } 1673185Seric if (q == NULL || bitset(QDONTSEND, q->q_flags)) 1681874Seric continue; 1691874Seric 1703185Seric /* 1713185Seric ** Match on Alias. 1723185Seric ** Deliver to the target list. 1733185Seric ** Remove the alias from the send queue 1743185Seric ** and put it on the Alias queue. 1753185Seric */ 176292Seric 177292Seric # ifdef DEBUG 1783185Seric if (Debug) 1793185Seric printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n", 1803185Seric q->q_paddr, q->q_host, q->q_user, 1813185Seric p, al.q_paddr, al.q_host, al.q_user); 182292Seric # endif 1834065Seric if (Verbose) 1844065Seric message("050", "aliased to %s", p); 1853185Seric q->q_flags |= QDONTSEND; 1863185Seric didalias++; 1873185Seric gotmatch++; 1883185Seric sendto(p, 1); 189292Seric } 1901503Smark } while (didalias); 191*4081Seric (void) fclose(af); 1921515Seric #else DBM 1931515Seric /* 1943185Seric ** Scan send queues 1951515Seric ** We only have to do this once, since anything we alias 1961874Seric ** to is being put at the end of the queue we are 1971515Seric ** scanning. 1981515Seric */ 1991515Seric 2003185Seric for (mno = 0; Mailer[mno] != NULL; mno++) 2011515Seric { 2023185Seric for (q = Mailer[mno]->m_sendq; q != NULL; q = q->q_next) 2031874Seric { 2044065Seric To = q->q_paddr; 2054065Seric 2063185Seric /* don't realias already aliased names */ 2073185Seric if (bitset(QDONTSEND, q->q_flags)) 2083185Seric continue; 2091874Seric 2103185Seric /* only alias local users */ 2114078Seric if (q->q_mailer != M_LOCAL) 2123185Seric continue; 2131622Seric 2143185Seric /* create a key for fetch */ 2153185Seric lhs.dptr = q->q_user; 2163185Seric lhs.dsize = strlen(q->q_user) + 1; 2173185Seric rhs = fetch(lhs); 2181515Seric 2193185Seric /* find this alias? */ 2203185Seric p = rhs.dptr; 2213185Seric if (p == NULL) 2223185Seric continue; 2231515Seric 2243185Seric /* 2253185Seric ** Match on Alias. 2263185Seric ** Deliver to the target list. 2273185Seric ** Remove the alias from the send queue 2283185Seric ** and put it on the Alias queue. 2293185Seric */ 2301515Seric 2311515Seric # ifdef DEBUG 2323185Seric if (Debug) 2333185Seric printf("%s (%s, %s) aliased to %s\n", 2343185Seric q->q_paddr, q->q_host, q->q_user, p); 2351515Seric # endif 2364065Seric if (Verbose) 2374065Seric message("050", "aliased to %s", p); 2383185Seric q->q_flags |= QDONTSEND; 2393185Seric sendto(p, 1); 2403185Seric } 2411515Seric } 2421515Seric #endif DBM 243292Seric } 244292Seric /* 245292Seric ** FORWARD -- Try to forward mail 246292Seric ** 247292Seric ** This is similar but not identical to aliasing. 248292Seric ** 249292Seric ** Currently it is undefined, until the protocol for userinfo 250292Seric ** databases is finalized. 251292Seric ** 252292Seric ** Parameters: 253292Seric ** user -- the name of the user who's mail we 254292Seric ** would like to forward to. 255292Seric ** 256292Seric ** Returns: 257292Seric ** TRUE -- we have forwarded it somewhere. 258292Seric ** FALSE -- not forwarded; go ahead & deliver. 259292Seric ** 260292Seric ** Side Effects: 2613185Seric ** New names are added to send queues. 262292Seric */ 263292Seric 264292Seric bool 265292Seric forward(user) 2662966Seric ADDRESS *user; 267292Seric { 2684078Seric char buf[60]; 2694069Seric register FILE *fp; 2704069Seric register char *p; 2714069Seric 2724078Seric if (user->q_mailer != M_LOCAL || bitset(QBADADDR, user->q_flags)) 2734069Seric return (FALSE); 2744069Seric 2754069Seric /* good address -- look for .forward file in home */ 276*4081Seric (void) expand("$z/.forward", buf, &buf[sizeof buf - 1]); 2774069Seric fp = fopen(buf, "r"); 2784069Seric if (fp == NULL) 2794069Seric return (FALSE); 2804069Seric 2814069Seric /* we do have an address to forward to -- do it */ 282*4081Seric (void) fgets(buf, sizeof buf, fp); 2834069Seric if ((p = index(buf, '\n')) != NULL) 2844069Seric *p = '\0'; 285*4081Seric (void) fclose(fp); 2864069Seric if (buf[0] == '\0') 2874069Seric return (FALSE); 2884069Seric if (Verbose) 2894069Seric message("050", "forwarded to %s", buf); 2904069Seric sendto(buf, 1); 2914069Seric return (TRUE); 292292Seric } 293