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