1: # include <stdio.h> 2: # include <ctype.h> 3: # include <pwd.h> 4: # include "dlvrmail.h" 5: 6: static char SccsId[] = "@(#)alias.c 2.2 12/6/80"; 7: 8: /* 9: ** ALIAS -- Compute aliases. 10: ** 11: ** Scans the file ALIASFILE for a set of aliases. 12: ** If found, it arranges to deliver to them by inserting the 13: ** new names onto the SendQ queue. Uses libdbm database if -DDBM. 14: ** 15: ** Parameters: 16: ** none 17: ** 18: ** Returns: 19: ** none 20: ** 21: ** Side Effects: 22: ** Aliases found on SendQ are removed and put onto 23: ** AliasQ; replacements are added to SendQ. This is 24: ** done until no such replacement occurs. 25: ** 26: ** Defined Constants: 27: ** MAXRCRSN -- the maximum recursion depth. 28: ** 29: ** Called By: 30: ** main 31: ** 32: ** Files: 33: ** ALIASFILE -- the mail aliases. The format is 34: ** a series of lines of the form: 35: ** alias:name1,name2,name3,... 36: ** where 'alias' expands to all of 37: ** 'name[i]'. Continuations begin with 38: ** space or tab. 39: ** ALIASFILE.pag, ALIASFILE.dir: libdbm version 40: ** of alias file. Keys are aliases, datums 41: ** (data?) are name1,name2, ... 42: ** 43: ** Notes: 44: ** If NoAlias (the "-n" flag) is set, no aliasing is 45: ** done. 46: ** 47: ** Deficiencies: 48: ** It should complain about names that are aliased to 49: ** nothing. 50: ** It is unsophisticated about line overflows. 51: */ 52: 53: 54: # define MAXRCRSN 10 55: 56: #ifdef DBM 57: typedef struct {char *dptr; int dsize;} datum; 58: datum lhs, rhs; 59: extern datum fetch(); 60: #endif DBM 61: 62: alias() 63: { 64: register addrq *q; 65: addrq *q2; 66: FILE *af; 67: char line[MAXLINE+1]; 68: register char *p; 69: extern int errno; 70: bool didalias; 71: bool gotmatch; 72: auto addrq al; 73: extern bool sameaddr(); 74: extern addrq *parse(); 75: 76: if (NoAlias) 77: return; 78: # ifdef DEBUG 79: if (Debug) 80: printf("--- alias ---\n"); 81: # endif 82: 83: /* open alias file if not already open */ 84: #ifndef DBM 85: # ifdef DEBUG 86: if (Debug && (af = fopen("mailaliases", "r")) != NULL) 87: printf(" [using local alias file]\n"); 88: else 89: # endif 90: if ((af = fopen(ALIASFILE, "r")) == NULL) 91: { 92: # ifdef DEBUG 93: if (Debug) 94: printf("Can't open %s\n", ALIASFILE); 95: # endif 96: errno = 0; 97: return; 98: } 99: #else DBM 100: dbminit(ALIASFILE); 101: #endif DBM 102: 103: #ifndef DBM 104: /* 105: ** Scan alias file. 106: ** If we find any user that any line matches any user, we 107: ** will send to the line rather than to the user. 108: ** 109: ** We pass through the file several times. Didalias tells 110: ** us if we took some alias on this pass through the file; 111: ** when it goes false at the top of the loop we don't have 112: ** to scan any more. Gotmatch tells the same thing, but 113: ** on a line-by-line basis; it is used for processing 114: ** continuation lines. 115: */ 116: 117: do 118: { 119: didalias = FALSE; 120: gotmatch = FALSE; 121: rewind(af); 122: while (fgets(line, sizeof line, af) != NULL) 123: { 124: /* comments begin with `#' */ 125: if (line[0] == '#') 126: continue; 127: 128: /* check for continuation lines */ 129: if (isspace(line[0])) 130: { 131: if (gotmatch) 132: { 133: sendto(line, 1); 134: } 135: continue; 136: } 137: gotmatch = FALSE; 138: 139: /* 140: ** Check to see if this pseudonym exists in SendQ. 141: ** Turn the alias into canonical form. 142: ** Then scan SendQ until you do (or do not) 143: ** find that address. 144: */ 145: 146: /* Get a canonical form for the alias. */ 147: for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 148: continue; 149: if (*p == '\0' || *p == '\n') 150: { 151: syntaxerr: 152: syserr("Bad alias line `%s'", line); 153: continue; 154: } 155: *p++ = '\0'; 156: if (parse(line, &al, -1) == NULL) 157: { 158: *--p = ':'; 159: goto syntaxerr; 160: } 161: 162: /* if already in AliasQ don't realias */ 163: for (q = &AliasQ; (q = nxtinq(q)) != NULL; ) 164: { 165: if (sameaddr(&al, q, TRUE)) 166: break; 167: } 168: if (q != NULL) 169: continue; 170: 171: /* Scan SendQ for that canonical form. */ 172: for (q = &SendQ; (q = nxtinq(q)) != NULL; ) 173: { 174: if (sameaddr(&al, q, TRUE)) 175: break; 176: } 177: if (q != NULL) 178: { 179: /* 180: ** Match on Alias. 181: ** Deliver to the target list. 182: ** Remove the alias from the send queue 183: ** and put it on the Alias queue. 184: */ 185: 186: # ifdef DEBUG 187: if (Debug) 188: printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n", 189: q->q_paddr, q->q_host, q->q_user, 190: p, al.q_paddr, al.q_host, al.q_user); 191: # endif 192: tkoffq(q, &SendQ); 193: didalias++; 194: gotmatch++; 195: sendto(p, 1); 196: putonq(q, &AliasQ); 197: } 198: } 199: } while (didalias); 200: fclose(af); 201: #else DBM 202: /* 203: ** Scan SendQ 204: ** We only have to do this once, since anything we alias 205: ** to is being put at the end of the queue we are 206: ** scanning. 207: ** If the alias on SendQ is also (already) on AliasQ, we 208: ** have an alias such as: 209: ** eric:eric,i:eric 210: ** In this case we have already done this alias once, and 211: ** we don't want to do it again (for obvious reasons!). 212: */ 213: 214: for (q2 = nxtinq(&SendQ); q2 != NULL; ) 215: { 216: /* if already in AliasQ, don't realias */ 217: for (q = &AliasQ; (q = nxtinq(q)) != NULL; ) 218: { 219: if (sameaddr(q, q2, TRUE)) 220: break; 221: } 222: if (q != NULL) 223: { 224: q2 = nxtinq(q2); 225: continue; 226: } 227: 228: /* save ptr to next address */ 229: q = q2; 230: q2 = nxtinq(q); 231: 232: /* only alias local users */ 233: if (q->q_mailer != &Mailer[0]) 234: continue; 235: 236: /* create a key for fetch */ 237: lhs.dptr = q->q_user; 238: lhs.dsize = strlen(q->q_user) + 1; 239: rhs = fetch(lhs); 240: 241: /* find this alias? */ 242: p = rhs.dptr; 243: if (p == NULL) 244: continue; 245: 246: /* 247: ** Match on Alias. 248: ** Deliver to the target list. 249: ** Remove the alias from the send queue 250: ** and put it on the Alias queue. 251: */ 252: 253: # ifdef DEBUG 254: if (Debug) 255: printf("%s (%s, %s) aliased to %s\n", 256: q->q_paddr, q->q_host, q->q_user, p); 257: # endif 258: tkoffq(q, &SendQ); 259: sendto(p, 1); 260: putonq(q, &AliasQ); 261: 262: /* if our last entry had an alias, process them */ 263: if (q2 == NULL) 264: q2 = nxtinq(&SendQ); 265: } 266: #endif DBM 267: } 268: /* 269: ** FORWARD -- Try to forward mail 270: ** 271: ** This is similar but not identical to aliasing. 272: ** 273: ** Currently it is undefined, until the protocol for userinfo 274: ** databases is finalized. 275: ** 276: ** Parameters: 277: ** user -- the name of the user who's mail we 278: ** would like to forward to. 279: ** 280: ** Returns: 281: ** TRUE -- we have forwarded it somewhere. 282: ** FALSE -- not forwarded; go ahead & deliver. 283: ** 284: ** Side Effects: 285: ** New names are added to SendQ. 286: ** 287: ** Called By: 288: ** recipient 289: */ 290: 291: bool 292: forward(user) 293: addrq *user; 294: { 295: return (FALSE); 296: }