1 # include <stdio.h> 2 # include <ctype.h> 3 # include <pwd.h> 4 # include "sendmail.h" 5 6 static char SccsId[] = "@(#)alias.c 3.11 08/10/81"; 7 8 /* 9 ** ALIAS -- Compute aliases. 10 ** 11 ** Scans the file /usr/lib/aliases for a set of aliases. 12 ** If found, it arranges to deliver to them. Uses libdbm 13 ** database if -DDBM. 14 ** 15 ** Parameters: 16 ** a -- address to alias. 17 ** 18 ** Returns: 19 ** none 20 ** 21 ** Side Effects: 22 ** Aliases found are expanded. 23 ** 24 ** Files: 25 ** /usr/lib/aliases -- the mail aliases. The format is 26 ** a series of lines of the form: 27 ** alias:name1,name2,name3,... 28 ** where 'alias' expands to all of 29 ** 'name[i]'. Continuations begin with 30 ** space or tab. 31 ** /usr/lib/aliases.pag, /usr/lib/aliases.dir: libdbm version 32 ** of alias file. Keys are aliases, datums 33 ** (data?) are name1,name2, ... 34 ** 35 ** Notes: 36 ** If NoAlias (the "-n" flag) is set, no aliasing is 37 ** done. 38 ** 39 ** Deficiencies: 40 ** It should complain about names that are aliased to 41 ** nothing. 42 ** It is unsophisticated about line overflows. 43 */ 44 45 46 #ifdef DBM 47 typedef struct 48 { 49 char *dptr; 50 int dsize; 51 } datum; 52 datum lhs, rhs; 53 extern datum fetch(); 54 #endif DBM 55 56 alias(a) 57 register ADDRESS *a; 58 { 59 register char *p; 60 # ifndef DBM 61 register STAB *s; 62 # endif DBM 63 64 if (NoAlias) 65 return; 66 # ifdef DEBUG 67 if (Debug) 68 printf("alias(%s)\n", a->q_paddr); 69 # endif 70 71 /* don't realias already aliased names */ 72 if (bitset(QDONTSEND, a->q_flags)) 73 return; 74 75 To = a->q_paddr; 76 77 # ifdef DBM 78 /* create a key for fetch */ 79 lhs.dptr = a->q_user; 80 lhs.dsize = strlen(a->q_user) + 1; 81 rhs = fetch(lhs); 82 83 /* find this alias? */ 84 p = rhs.dptr; 85 if (p == NULL) 86 return; 87 # else DBM 88 s = stab(a->q_user, ST_ALIAS, ST_FIND); 89 if (s == NULL) 90 return; 91 p = s->s_alias; 92 # endif DBM 93 94 /* 95 ** Match on Alias. 96 ** Deliver to the target list. 97 */ 98 99 # ifdef DEBUG 100 if (Debug) 101 printf("%s (%s, %s) aliased to %s\n", 102 a->q_paddr, a->q_host, a->q_user, p); 103 # endif 104 if (Verbose) 105 message("050", "aliased to %s", p); 106 a->q_flags |= QDONTSEND; 107 AliasLevel++; 108 sendto(p, 1); 109 AliasLevel--; 110 } 111 /* 112 ** INITALIASES -- initialize for aliasing 113 ** 114 ** Very different depending on whether we are running DBM or not. 115 ** 116 ** Parameters: 117 ** aliasfile -- location of aliases. 118 ** 119 ** Returns: 120 ** none. 121 ** 122 ** Side Effects: 123 ** initializes aliases: 124 ** if DBM: opens the database. 125 ** if ~DBM: reads the aliases into the symbol table. 126 */ 127 128 initaliases(aliasfile) 129 char *aliasfile; 130 { 131 # ifdef DBM 132 dbminit(aliasfile); 133 # else DBM 134 char line[BUFSIZ]; 135 register char *p; 136 char *p2; 137 char *rhs; 138 bool skipping; 139 ADDRESS al, bl; 140 extern char *prescan(); 141 bool contin; 142 143 if ((af = fopen(aliasfile, "r")) == NULL) 144 { 145 # ifdef DEBUG 146 if (Debug) 147 printf("Can't open %s\n", AliasFile); 148 # endif 149 errno = 0; 150 NoAlias++; 151 return; 152 } 153 /* read and interpret lines */ 154 lineno = 0; 155 skipping = FALSE; 156 while (fgets(line, sizeof (line), af) != NULL) 157 { 158 lineno++; 159 switch (line[0]) 160 { 161 case '#': 162 case '\n': 163 case '\0': 164 skipping = FALSE; 165 continue; 166 167 case ' ': 168 case '\t': 169 if (!skipping) 170 syserr("aliases: %d: Non-continuation line starts with space", lineno); 171 skipping = TRUE; 172 continue; 173 } 174 skipping = FALSE; 175 176 /* process the LHS */ 177 for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++) 178 continue; 179 if (*p == '\0' || *p == '\n') 180 { 181 syntaxerr: 182 syserr("aliases: %d: missing colon", lineno); 183 continue; 184 } 185 *p++ = '\0'; 186 if (parse(line, &al, 1) == NULL) 187 { 188 *--p = ':'; 189 goto syntaxerr; 190 } 191 rhs = p; 192 contin = FALSE; 193 for (;;) 194 { 195 register char c; 196 197 /* do parsing & compression of addresses */ 198 c = *p; 199 while (c != '\0') 200 { 201 p2 = p; 202 while (*p != '\n' && *p != ',' && *p != '\0') 203 p++; 204 c = *p; 205 *p++ = '\0'; 206 if (*p2 == '\0') 207 { 208 p[-1] = c; 209 continue; 210 } 211 parse(p2, &bl, -1); 212 contin = (c == ','); 213 p[-1] = c; 214 while (isspace(*p)) 215 p++; 216 } 217 218 /* see if there should be a continuation line */ 219 if (!contin) 220 break; 221 222 /* read continuation line */ 223 p--; 224 if (fgets(p, sizeof line - (p - line), af) == NULL) 225 break; 226 lineno++; 227 228 if (!isspace(*p)) 229 syserr("aliases: %d: continuation line missing", lineno); 230 } 231 if (al.q_mailer != M_LOCAL) 232 { 233 syserr("aliases: %d: cannot alias non-local names", lineno); 234 continue; 235 } 236 s = stab(al.q_user, ST_ALIAS, rhs); 237 } 238 (void) fclose(af); 239 # endif DBM 240 } 241 /* 242 ** FORWARD -- Try to forward mail 243 ** 244 ** This is similar but not identical to aliasing. 245 ** 246 ** Parameters: 247 ** user -- the name of the user who's mail we 248 ** would like to forward to. 249 ** 250 ** Returns: 251 ** none. 252 ** 253 ** Side Effects: 254 ** New names are added to send queues. 255 ** Sets the QDONTSEND bit in addresses that are forwarded. 256 */ 257 258 forward(user) 259 ADDRESS *user; 260 { 261 char buf[60]; 262 register FILE *fp; 263 register char *p; 264 265 # ifdef DEBUG 266 if (Debug) 267 printf("forward(%s)\n", user->q_paddr); 268 # endif DEBUG 269 270 if (user->q_mailer != M_LOCAL || bitset(QBADADDR, user->q_flags)) 271 return; 272 273 /* good address -- look for .forward file in home */ 274 define('z', user->q_home); 275 (void) expand("$z/.forward", buf, &buf[sizeof buf - 1]); 276 fp = fopen(buf, "r"); 277 if (fp == NULL) 278 return; 279 280 /* we do have an address to forward to -- do it */ 281 user->q_flags |= QDONTSEND; 282 (void) fgets(buf, sizeof buf, fp); 283 if ((p = index(buf, '\n')) != NULL) 284 *p = '\0'; 285 (void) fclose(fp); 286 if (buf[0] == '\0') 287 return; 288 if (Verbose) 289 message("050", "forwarded to %s", buf); 290 AliasLevel++; 291 sendto(buf, 1); 292 AliasLevel--; 293 return; 294 } 295