1 # include <stdio.h> 2 # include <ctype.h> 3 # include <pwd.h> 4 # include "postbox.h" 5 6 static char SccsId[] = "@(#)alias.c 3.3 03/11/81"; 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. Uses libdbm 13 ** database if -DDBM. 14 ** 15 ** Parameters: 16 ** none 17 ** 18 ** Returns: 19 ** none 20 ** 21 ** Side Effects: 22 ** Aliases found are expanded. 23 ** 24 ** Defined Constants: 25 ** MAXRCRSN -- the maximum recursion depth. 26 ** 27 ** Files: 28 ** ALIASFILE -- the mail aliases. The format is 29 ** a series of lines of the form: 30 ** alias:name1,name2,name3,... 31 ** where 'alias' expands to all of 32 ** 'name[i]'. Continuations begin with 33 ** space or tab. 34 ** ALIASFILE.pag, ALIASFILE.dir: libdbm version 35 ** of alias file. Keys are aliases, datums 36 ** (data?) are name1,name2, ... 37 ** 38 ** Notes: 39 ** If NoAlias (the "-n" flag) is set, no aliasing is 40 ** done. 41 ** 42 ** Deficiencies: 43 ** It should complain about names that are aliased to 44 ** nothing. 45 ** It is unsophisticated about line overflows. 46 */ 47 48 49 # define MAXRCRSN 10 50 51 #ifdef DBM 52 typedef struct 53 { 54 char *dptr; 55 int dsize; 56 } datum; 57 datum lhs, rhs; 58 extern datum fetch(); 59 #endif DBM 60 61 alias() 62 { 63 register ADDRESS *q; 64 ADDRESS *q2; 65 FILE *af; 66 char line[MAXLINE+1]; 67 register char *p; 68 extern int errno; 69 bool didalias; 70 bool gotmatch; 71 auto ADDRESS al; 72 extern bool sameaddr(); 73 extern ADDRESS *parse(); 74 int mno; 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. 141 ** Turn the alias into canonical form. 142 ** Then scan the send queue until you 143 ** do (or do not) 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 queued up, don't realias */ 163 for (q = Mailer[al.q_mailer]->m_sendq; q != NULL; q = q->q_next) 164 { 165 if (sameaddr(&al, q, TRUE)) 166 break; 167 } 168 if (q == NULL || bitset(QDONTSEND, q->q_flags)) 169 continue; 170 171 /* 172 ** Match on Alias. 173 ** Deliver to the target list. 174 ** Remove the alias from the send queue 175 ** and put it on the Alias queue. 176 */ 177 178 # ifdef DEBUG 179 if (Debug) 180 printf("%s (%s, %s) aliased to %s (%s,%s,%s)\n", 181 q->q_paddr, q->q_host, q->q_user, 182 p, al.q_paddr, al.q_host, al.q_user); 183 # endif 184 q->q_flags |= QDONTSEND; 185 didalias++; 186 gotmatch++; 187 sendto(p, 1); 188 } 189 } while (didalias); 190 fclose(af); 191 #else DBM 192 /* 193 ** Scan send queues 194 ** We only have to do this once, since anything we alias 195 ** to is being put at the end of the queue we are 196 ** scanning. 197 */ 198 199 for (mno = 0; Mailer[mno] != NULL; mno++) 200 { 201 for (q = Mailer[mno]->m_sendq; q != NULL; q = q->q_next) 202 { 203 /* don't realias already aliased names */ 204 if (bitset(QDONTSEND, q->q_flags)) 205 continue; 206 207 /* only alias local users */ 208 if (q->q_mailer != 0) 209 continue; 210 211 /* create a key for fetch */ 212 lhs.dptr = q->q_user; 213 lhs.dsize = strlen(q->q_user) + 1; 214 rhs = fetch(lhs); 215 216 /* find this alias? */ 217 p = rhs.dptr; 218 if (p == NULL) 219 continue; 220 221 /* 222 ** Match on Alias. 223 ** Deliver to the target list. 224 ** Remove the alias from the send queue 225 ** and put it on the Alias queue. 226 */ 227 228 # ifdef DEBUG 229 if (Debug) 230 printf("%s (%s, %s) aliased to %s\n", 231 q->q_paddr, q->q_host, q->q_user, p); 232 # endif 233 q->q_flags |= QDONTSEND; 234 sendto(p, 1); 235 } 236 } 237 #endif DBM 238 } 239 /* 240 ** FORWARD -- Try to forward mail 241 ** 242 ** This is similar but not identical to aliasing. 243 ** 244 ** Currently it is undefined, until the protocol for userinfo 245 ** databases is finalized. 246 ** 247 ** Parameters: 248 ** user -- the name of the user who's mail we 249 ** would like to forward to. 250 ** 251 ** Returns: 252 ** TRUE -- we have forwarded it somewhere. 253 ** FALSE -- not forwarded; go ahead & deliver. 254 ** 255 ** Side Effects: 256 ** New names are added to send queues. 257 */ 258 259 bool 260 forward(user) 261 ADDRESS *user; 262 { 263 return (FALSE); 264 } 265