1292Seric # include <stdio.h> 2292Seric # include <ctype.h> 3292Seric # include <pwd.h> 4292Seric # include "dlvrmail.h" 5292Seric 6*1515Seric static char SccsId[] = "@(#)alias.c 1.5 10/18/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; 59*1515Seric extern datum fetch(); 601503Smark #endif DBM 61292Seric 62292Seric alias() 63292Seric { 64292Seric register addrq *q; 65292Seric FILE *af; 66292Seric char line[MAXLINE+1]; 67292Seric register char *p; 68292Seric extern int errno; 69292Seric bool didalias; 70292Seric bool gotmatch; 71292Seric auto addrq al; 72292Seric extern bool sameaddr(); 73292Seric extern addrq *parse(); 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 /* 139292Seric ** Check to see if this pseudonym exists in SendQ. 140292Seric ** Turn the alias into canonical form. 141292Seric ** Then scan SendQ until you do (or do not) 142292Seric ** 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 161292Seric /* Scan SendQ for that canonical form. */ 162292Seric for (q = &SendQ; (q = nxtinq(q)) != NULL; ) 163292Seric { 164292Seric if (sameaddr(&al, q, TRUE)) 165292Seric break; 166292Seric } 167292Seric if (q != NULL) 168292Seric { 169292Seric /* 170292Seric ** Match on Alias. 171292Seric ** Deliver to the target list. 172292Seric ** Remove the alias from the send queue 173292Seric ** and put it on the Alias queue. 174292Seric */ 175292Seric 176292Seric # ifdef DEBUG 177292Seric if (Debug) 178292Seric printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n", 179292Seric q->q_paddr, q->q_host, q->q_user, 180292Seric p, al.q_paddr, al.q_host, al.q_user); 181292Seric # endif 182292Seric tkoffq(q, &SendQ); 183292Seric putonq(q, &AliasQ); 184292Seric didalias++; 185292Seric gotmatch++; 186292Seric sendto(p, 1); 187292Seric } 188292Seric } 1891503Smark } while (didalias); 190292Seric fclose(af); 191*1515Seric #else DBM 192*1515Seric /* 193*1515Seric ** Scan SendQ 194*1515Seric ** We only have to do this once, since anything we alias 195*1515Seric ** two is being put at the end of the queue we are 196*1515Seric ** scanning. 197*1515Seric */ 198*1515Seric 199*1515Seric for (q = &SendQ; (q = nxtinq(q)) != NULL; ) 200*1515Seric { 201*1515Seric /* only alias local users */ 202*1515Seric if (q->q_mailer != &Mailer[0]) 203*1515Seric continue; 204*1515Seric 205*1515Seric /* create a key for fetch */ 206*1515Seric lhs.dptr = q->q_user; 207*1515Seric lhs.dsize = strlen(q->q_user) + 1; 208*1515Seric lhs.dptr = line; 209*1515Seric rhs = fetch(lhs); 210*1515Seric 211*1515Seric /* find this alias? */ 212*1515Seric p = rhs.dptr; 213*1515Seric if (p == NULL) 214*1515Seric continue; 215*1515Seric 216*1515Seric /* 217*1515Seric ** Match on Alias. 218*1515Seric ** Deliver to the target list. 219*1515Seric ** Remove the alias from the send queue 220*1515Seric ** and put it on the Alias queue. 221*1515Seric */ 222*1515Seric 223*1515Seric # ifdef DEBUG 224*1515Seric if (Debug) 225*1515Seric printf("%s (%s, %s) aliased to %s\n", 226*1515Seric q->q_paddr, q->q_host, q->q_user, p); 227*1515Seric # endif 228*1515Seric tkoffq(q, &SendQ); 229*1515Seric putonq(q, &AliasQ); 230*1515Seric sendto(p, 1); 231*1515Seric } 232*1515Seric #endif DBM 233292Seric } 234292Seric /* 235292Seric ** FORWARD -- Try to forward mail 236292Seric ** 237292Seric ** This is similar but not identical to aliasing. 238292Seric ** 239292Seric ** Currently it is undefined, until the protocol for userinfo 240292Seric ** databases is finalized. 241292Seric ** 242292Seric ** Parameters: 243292Seric ** user -- the name of the user who's mail we 244292Seric ** would like to forward to. 245292Seric ** 246292Seric ** Returns: 247292Seric ** TRUE -- we have forwarded it somewhere. 248292Seric ** FALSE -- not forwarded; go ahead & deliver. 249292Seric ** 250292Seric ** Side Effects: 251292Seric ** New names are added to SendQ. 252292Seric ** 253292Seric ** Called By: 254292Seric ** recipient 255292Seric */ 256292Seric 257292Seric bool 258292Seric forward(user) 259292Seric addrq *user; 260292Seric { 261292Seric return (FALSE); 262292Seric } 263