1 # include <stdio.h> 2 # include <ctype.h> 3 # include <pwd.h> 4 # include "dlvrmail.h" 5 6 static char SccsId[] = "@(#)alias.c 2.1 11/05/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 /* Scan SendQ for that canonical form. */ 163 for (q = &SendQ; (q = nxtinq(q)) != NULL; ) 164 { 165 if (sameaddr(&al, q, TRUE)) 166 break; 167 } 168 if (q != NULL) 169 { 170 /* 171 ** Match on Alias. 172 ** Deliver to the target list. 173 ** Remove the alias from the send queue 174 ** and put it on the Alias queue. 175 */ 176 177 # ifdef DEBUG 178 if (Debug) 179 printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n", 180 q->q_paddr, q->q_host, q->q_user, 181 p, al.q_paddr, al.q_host, al.q_user); 182 # endif 183 tkoffq(q, &SendQ); 184 putonq(q, &AliasQ); 185 didalias++; 186 gotmatch++; 187 sendto(p, 1); 188 } 189 } 190 } while (didalias); 191 fclose(af); 192 #else DBM 193 /* 194 ** Scan SendQ 195 ** We only have to do this once, since anything we alias 196 ** two is being put at the end of the queue we are 197 ** scanning. 198 */ 199 200 for (q2 = nxtinq(&SendQ); (q = q2) != NULL; ) 201 { 202 /* save ptr to next address */ 203 q2 = nxtinq(q); 204 205 /* only alias local users */ 206 if (q->q_mailer != &Mailer[0]) 207 continue; 208 209 /* create a key for fetch */ 210 lhs.dptr = q->q_user; 211 lhs.dsize = strlen(q->q_user) + 1; 212 rhs = fetch(lhs); 213 214 /* find this alias? */ 215 p = rhs.dptr; 216 if (p == NULL) 217 continue; 218 219 /* 220 ** Match on Alias. 221 ** Deliver to the target list. 222 ** Remove the alias from the send queue 223 ** and put it on the Alias queue. 224 */ 225 226 # ifdef DEBUG 227 if (Debug) 228 printf("%s (%s, %s) aliased to %s\n", 229 q->q_paddr, q->q_host, q->q_user, p); 230 # endif 231 tkoffq(q, &SendQ); 232 putonq(q, &AliasQ); 233 sendto(p, 1); 234 235 /* if our last entry had an alias, process them */ 236 if (q2 == NULL) 237 q2 = nxtinq(&SendQ); 238 } 239 #endif DBM 240 } 241 /* 242 ** FORWARD -- Try to forward mail 243 ** 244 ** This is similar but not identical to aliasing. 245 ** 246 ** Currently it is undefined, until the protocol for userinfo 247 ** databases is finalized. 248 ** 249 ** Parameters: 250 ** user -- the name of the user who's mail we 251 ** would like to forward to. 252 ** 253 ** Returns: 254 ** TRUE -- we have forwarded it somewhere. 255 ** FALSE -- not forwarded; go ahead & deliver. 256 ** 257 ** Side Effects: 258 ** New names are added to SendQ. 259 ** 260 ** Called By: 261 ** recipient 262 */ 263 264 bool 265 forward(user) 266 addrq *user; 267 { 268 return (FALSE); 269 } 270