Deleted Added
full compact
alias.c (302408) alias.c (38032)
1/*
1/*
2 * Copyright (c) 1998-2003 Proofpoint, Inc. and its suppliers.
3 * All rights reserved.
2 * Copyright (c) 1998 Sendmail, Inc. All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
3 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
5 * Copyright (c) 1988, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 * Copyright (c) 1988, 1993
10 * The Regents of the University of California. All rights reserved.
12 */
13
11 */
12
14#include <sendmail.h>
13# include "sendmail.h"
15
14
16SM_RCSID("@(#)$Id: alias.c,v 8.221 2013-11-22 20:51:54 ca Exp $")
15#ifndef lint
16static char sccsid[] = "@(#)alias.c 8.92 (Berkeley) 6/5/98";
17#endif /* not lint */
17
18
18#define SEPARATOR ':'
19# define ALIAS_SPEC_SEPARATORS " ,/:"
20
19
21static MAP *AliasFileMap = NULL; /* the actual aliases.files map */
22static int NAliasFileMaps; /* the number of entries in AliasFileMap */
23
24static char *aliaslookup __P((char *, int *, char *));
25
26/*
20MAP *AliasFileMap = NULL; /* the actual aliases.files map */
21int NAliasFileMaps; /* the number of entries in AliasFileMap */
22 /*
27** ALIAS -- Compute aliases.
28**
29** Scans the alias file for an alias for the given address.
30** If found, it arranges to deliver to the alias list instead.
31** Uses libdbm database if -DDBM.
32**
33** Parameters:
34** a -- address to alias.

--- 17 unchanged lines hidden (view full) ---

52alias(a, sendq, aliaslevel, e)
53 register ADDRESS *a;
54 ADDRESS **sendq;
55 int aliaslevel;
56 register ENVELOPE *e;
57{
58 register char *p;
59 char *owner;
23** ALIAS -- Compute aliases.
24**
25** Scans the alias file for an alias for the given address.
26** If found, it arranges to deliver to the alias list instead.
27** Uses libdbm database if -DDBM.
28**
29** Parameters:
30** a -- address to alias.

--- 17 unchanged lines hidden (view full) ---

48alias(a, sendq, aliaslevel, e)
49 register ADDRESS *a;
50 ADDRESS **sendq;
51 int aliaslevel;
52 register ENVELOPE *e;
53{
54 register char *p;
55 char *owner;
60 auto int status = EX_OK;
56 auto int stat = EX_OK;
61 char obuf[MAXNAME + 7];
57 char obuf[MAXNAME + 7];
58 extern char *aliaslookup __P((char *, int *, ENVELOPE *));
62
63 if (tTd(27, 1))
59
60 if (tTd(27, 1))
64 sm_dprintf("alias(%s)\n", a->q_user);
61 printf("alias(%s)\n", a->q_user);
65
66 /* don't realias already aliased names */
62
63 /* don't realias already aliased names */
67 if (!QS_IS_OK(a->q_state))
64 if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags))
68 return;
69
70 if (NoAlias)
71 return;
72
73 e->e_to = a->q_paddr;
74
75 /*
76 ** Look up this name.
77 **
78 ** If the map was unavailable, we will queue this message
79 ** until the map becomes available; otherwise, we could
80 ** bounce messages inappropriately.
81 */
82
65 return;
66
67 if (NoAlias)
68 return;
69
70 e->e_to = a->q_paddr;
71
72 /*
73 ** Look up this name.
74 **
75 ** If the map was unavailable, we will queue this message
76 ** until the map becomes available; otherwise, we could
77 ** bounce messages inappropriately.
78 */
79
83#if _FFR_REDIRECTEMPTY
84 /*
85 ** envelope <> can't be sent to mailing lists, only owner-
86 ** send spam of this type to owner- of the list
87 ** ---- to stop spam from going to mailing lists!
88 */
89
90 if (e->e_sender != NULL && *e->e_sender == '\0')
80 p = aliaslookup(a->q_user, &stat, e);
81 if (stat == EX_TEMPFAIL || stat == EX_UNAVAILABLE)
91 {
82 {
92 /* Look for owner of alias */
93 (void) sm_strlcpyn(obuf, sizeof(obuf), 2, "owner-", a->q_user);
94 if (aliaslookup(obuf, &status, a->q_host) != NULL)
95 {
96 if (LogLevel > 8)
97 sm_syslog(LOG_WARNING, e->e_id,
98 "possible spam from <> to list: %s, redirected to %s\n",
99 a->q_user, obuf);
100 a->q_user = sm_rpool_strdup_x(e->e_rpool, obuf);
101 }
102 }
103#endif /* _FFR_REDIRECTEMPTY */
104
105 p = aliaslookup(a->q_user, &status, a->q_host);
106 if (status == EX_TEMPFAIL || status == EX_UNAVAILABLE)
107 {
108 a->q_state = QS_QUEUEUP;
83 a->q_flags |= QQUEUEUP;
109 if (e->e_message == NULL)
84 if (e->e_message == NULL)
110 e->e_message = sm_rpool_strdup_x(e->e_rpool,
111 "alias database unavailable");
112
113 /* XXX msg only per recipient? */
114 if (a->q_message == NULL)
115 a->q_message = "alias database unavailable";
85 e->e_message = newstr("alias database unavailable");
116 return;
117 }
118 if (p == NULL)
119 return;
120
121 /*
122 ** Match on Alias.
123 ** Deliver to the target list.
124 */
125
126 if (tTd(27, 1))
86 return;
87 }
88 if (p == NULL)
89 return;
90
91 /*
92 ** Match on Alias.
93 ** Deliver to the target list.
94 */
95
96 if (tTd(27, 1))
127 sm_dprintf("%s (%s, %s) aliased to %s\n",
128 a->q_paddr, a->q_host, a->q_user, p);
97 printf("%s (%s, %s) aliased to %s\n",
98 a->q_paddr, a->q_host, a->q_user, p);
129 if (bitset(EF_VRFYONLY, e->e_flags))
130 {
99 if (bitset(EF_VRFYONLY, e->e_flags))
100 {
131 a->q_state = QS_VERIFIED;
101 a->q_flags |= QVERIFIED;
132 return;
133 }
134 message("aliased to %s", shortenstring(p, MAXSHORTSTR));
102 return;
103 }
104 message("aliased to %s", shortenstring(p, MAXSHORTSTR));
135 if (LogLevel > 10)
105 if (LogLevel > 9)
136 sm_syslog(LOG_INFO, e->e_id,
106 sm_syslog(LOG_INFO, e->e_id,
137 "alias %.100s => %s",
138 a->q_paddr, shortenstring(p, MAXSHORTSTR));
107 "alias %.100s => %s",
108 a->q_paddr, shortenstring(p, MAXSHORTSTR));
139 a->q_flags &= ~QSELFREF;
140 if (tTd(27, 5))
141 {
109 a->q_flags &= ~QSELFREF;
110 if (tTd(27, 5))
111 {
142 sm_dprintf("alias: QS_EXPANDED ");
143 printaddr(sm_debug_file(), a, false);
112 printf("alias: QDONTSEND ");
113 printaddr(a, FALSE);
144 }
114 }
145 a->q_state = QS_EXPANDED;
146
147 /*
148 ** Always deliver aliased items as the default user.
149 ** Setting q_gid to 0 forces deliver() to use DefUser
150 ** instead of the alias name for the call to initgroups().
151 */
152
153 a->q_uid = DefUid;
154 a->q_gid = 0;
155 a->q_fullname = NULL;
156 a->q_flags |= QGOODUID|QALIAS;
157
115 a->q_flags |= QDONTSEND;
158 (void) sendtolist(p, a, sendq, aliaslevel + 1, e);
116 (void) sendtolist(p, a, sendq, aliaslevel + 1, e);
117 if (bitset(QSELFREF, a->q_flags))
118 a->q_flags &= ~QDONTSEND;
159
119
160 if (bitset(QSELFREF, a->q_flags) && QS_IS_EXPANDED(a->q_state))
161 a->q_state = QS_OK;
162
163 /*
164 ** Look for owner of alias
165 */
166
120 /*
121 ** Look for owner of alias
122 */
123
124 (void) strcpy(obuf, "owner-");
167 if (strncmp(a->q_user, "owner-", 6) == 0 ||
125 if (strncmp(a->q_user, "owner-", 6) == 0 ||
168 strlen(a->q_user) > sizeof(obuf) - 7)
169 (void) sm_strlcpy(obuf, "owner-owner", sizeof(obuf));
126 strlen(a->q_user) > (SIZE_T) sizeof obuf - 7)
127 (void) strcat(obuf, "owner");
170 else
128 else
171 (void) sm_strlcpyn(obuf, sizeof(obuf), 2, "owner-", a->q_user);
172 owner = aliaslookup(obuf, &status, a->q_host);
129 (void) strcat(obuf, a->q_user);
130 owner = aliaslookup(obuf, &stat, e);
173 if (owner == NULL)
174 return;
175
176 /* reflect owner into envelope sender */
177 if (strpbrk(owner, ",:/|\"") != NULL)
178 owner = obuf;
131 if (owner == NULL)
132 return;
133
134 /* reflect owner into envelope sender */
135 if (strpbrk(owner, ",:/|\"") != NULL)
136 owner = obuf;
179 a->q_owner = sm_rpool_strdup_x(e->e_rpool, owner);
137 a->q_owner = newstr(owner);
180
181 /* announce delivery to this alias; NORECEIPT bit set later */
182 if (e->e_xfp != NULL)
138
139 /* announce delivery to this alias; NORECEIPT bit set later */
140 if (e->e_xfp != NULL)
183 (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
184 "Message delivered to mailing list %s\n",
185 a->q_paddr);
141 fprintf(e->e_xfp, "Message delivered to mailing list %s\n",
142 a->q_paddr);
186 e->e_flags |= EF_SENDRECEIPT;
187 a->q_flags |= QDELIVERED|QEXPANDED;
188}
143 e->e_flags |= EF_SENDRECEIPT;
144 a->q_flags |= QDELIVERED|QEXPANDED;
145}
189/*
146 /*
190** ALIASLOOKUP -- look up a name in the alias file.
191**
192** Parameters:
193** name -- the name to look up.
194** pstat -- a pointer to a place to put the status.
147** ALIASLOOKUP -- look up a name in the alias file.
148**
149** Parameters:
150** name -- the name to look up.
151** pstat -- a pointer to a place to put the status.
195** av -- argument for %1 expansion.
152** e -- the current envelope.
196**
197** Returns:
198** the value of name.
199** NULL if unknown.
200**
201** Side Effects:
202** none.
203**
204** Warnings:
205** The return value will be trashed across calls.
206*/
207
153**
154** Returns:
155** the value of name.
156** NULL if unknown.
157**
158** Side Effects:
159** none.
160**
161** Warnings:
162** The return value will be trashed across calls.
163*/
164
208static char *
209aliaslookup(name, pstat, av)
165char *
166aliaslookup(name, pstat, e)
210 char *name;
211 int *pstat;
167 char *name;
168 int *pstat;
212 char *av;
169 ENVELOPE *e;
213{
214 static MAP *map = NULL;
170{
171 static MAP *map = NULL;
215#if _FFR_ALIAS_DETAIL
216 int i;
217 char *argv[4];
218#endif /* _FFR_ALIAS_DETAIL */
219
220 if (map == NULL)
221 {
222 STAB *s = stab("aliases", ST_MAP, ST_FIND);
223
224 if (s == NULL)
225 return NULL;
226 map = &s->s_map;
227 }
172
173 if (map == NULL)
174 {
175 STAB *s = stab("aliases", ST_MAP, ST_FIND);
176
177 if (s == NULL)
178 return NULL;
179 map = &s->s_map;
180 }
228 DYNOPENMAP(map);
181 if (!bitset(MF_OPEN, map->map_mflags))
182 return NULL;
229
230 /* special case POstMastER -- always use lower case */
183
184 /* special case POstMastER -- always use lower case */
231 if (sm_strcasecmp(name, "postmaster") == 0)
185 if (strcasecmp(name, "postmaster") == 0)
232 name = "postmaster";
233
186 name = "postmaster";
187
234#if _FFR_ALIAS_DETAIL
235 i = 0;
236 argv[i++] = name;
237 argv[i++] = av;
238
239 /* XXX '+' is hardwired here as delimiter! */
240 if (av != NULL && *av == '+')
241 argv[i++] = av + 1;
242 argv[i++] = NULL;
243 return (*map->map_class->map_lookup)(map, name, argv, pstat);
244#else /* _FFR_ALIAS_DETAIL */
245 return (*map->map_class->map_lookup)(map, name, NULL, pstat);
188 return (*map->map_class->map_lookup)(map, name, NULL, pstat);
246#endif /* _FFR_ALIAS_DETAIL */
247}
189}
248/*
190 /*
249** SETALIAS -- set up an alias map
250**
251** Called when reading configuration file.
252**
253** Parameters:
254** spec -- the alias specification
255**
256** Returns:

--- 5 unchanged lines hidden (view full) ---

262 char *spec;
263{
264 register char *p;
265 register MAP *map;
266 char *class;
267 STAB *s;
268
269 if (tTd(27, 8))
191** SETALIAS -- set up an alias map
192**
193** Called when reading configuration file.
194**
195** Parameters:
196** spec -- the alias specification
197**
198** Returns:

--- 5 unchanged lines hidden (view full) ---

204 char *spec;
205{
206 register char *p;
207 register MAP *map;
208 char *class;
209 STAB *s;
210
211 if (tTd(27, 8))
270 sm_dprintf("setalias(%s)\n", spec);
212 printf("setalias(%s)\n", spec);
271
272 for (p = spec; p != NULL; )
273 {
274 char buf[50];
275
276 while (isascii(*p) && isspace(*p))
277 p++;
278 if (*p == '\0')
279 break;
280 spec = p;
281
282 if (NAliasFileMaps >= MAXMAPSTACK)
283 {
284 syserr("Too many alias databases defined, %d max",
285 MAXMAPSTACK);
286 return;
287 }
288 if (AliasFileMap == NULL)
289 {
213
214 for (p = spec; p != NULL; )
215 {
216 char buf[50];
217
218 while (isascii(*p) && isspace(*p))
219 p++;
220 if (*p == '\0')
221 break;
222 spec = p;
223
224 if (NAliasFileMaps >= MAXMAPSTACK)
225 {
226 syserr("Too many alias databases defined, %d max",
227 MAXMAPSTACK);
228 return;
229 }
230 if (AliasFileMap == NULL)
231 {
290 (void) sm_strlcpy(buf, "aliases.files sequence",
291 sizeof(buf));
232 strcpy(buf, "aliases.files sequence");
292 AliasFileMap = makemapentry(buf);
293 if (AliasFileMap == NULL)
294 {
295 syserr("setalias: cannot create aliases.files map");
296 return;
297 }
298 }
233 AliasFileMap = makemapentry(buf);
234 if (AliasFileMap == NULL)
235 {
236 syserr("setalias: cannot create aliases.files map");
237 return;
238 }
239 }
299 (void) sm_snprintf(buf, sizeof(buf), "Alias%d", NAliasFileMaps);
240 (void) snprintf(buf, sizeof buf, "Alias%d", NAliasFileMaps);
300 s = stab(buf, ST_MAP, ST_ENTER);
301 map = &s->s_map;
241 s = stab(buf, ST_MAP, ST_ENTER);
242 map = &s->s_map;
302 memset(map, '\0', sizeof(*map));
243 bzero(map, sizeof *map);
303 map->map_mname = s->s_name;
244 map->map_mname = s->s_name;
304 p = strpbrk(p, ALIAS_SPEC_SEPARATORS);
305 if (p != NULL && *p == SEPARATOR)
245
246 p = strpbrk(p, " ,/:");
247 if (p != NULL && *p == ':')
306 {
307 /* map name */
308 *p++ = '\0';
309 class = spec;
310 spec = p;
311 }
312 else
313 {
314 class = "implicit";
315 map->map_mflags = MF_INCLNULL;
316 }
317
318 /* find end of spec */
319 if (p != NULL)
248 {
249 /* map name */
250 *p++ = '\0';
251 class = spec;
252 spec = p;
253 }
254 else
255 {
256 class = "implicit";
257 map->map_mflags = MF_INCLNULL;
258 }
259
260 /* find end of spec */
261 if (p != NULL)
320 {
321 bool quoted = false;
322
323 for (; *p != '\0'; p++)
324 {
325 /*
326 ** Don't break into a quoted string.
327 ** Needed for ldap maps which use
328 ** commas in their specifications.
329 */
330
331 if (*p == '"')
332 quoted = !quoted;
333 else if (*p == ',' && !quoted)
334 break;
335 }
336
337 /* No more alias specifications follow */
338 if (*p == '\0')
339 p = NULL;
340 }
262 p = strchr(p, ',');
341 if (p != NULL)
342 *p++ = '\0';
343
344 if (tTd(27, 20))
263 if (p != NULL)
264 *p++ = '\0';
265
266 if (tTd(27, 20))
345 sm_dprintf(" map %s:%s %s\n", class, s->s_name, spec);
267 printf(" map %s:%s %s\n", class, s->s_name, spec);
346
347 /* look up class */
348 s = stab(class, ST_MAPCLASS, ST_FIND);
349 if (s == NULL)
350 {
351 syserr("setalias: unknown alias class %s", class);
352 }
353 else if (!bitset(MCF_ALIASOK, s->s_mapclass.map_cflags))
354 {
355 syserr("setalias: map class %s can't handle aliases",
356 class);
357 }
358 else
359 {
360 map->map_class = &s->s_mapclass;
268
269 /* look up class */
270 s = stab(class, ST_MAPCLASS, ST_FIND);
271 if (s == NULL)
272 {
273 syserr("setalias: unknown alias class %s", class);
274 }
275 else if (!bitset(MCF_ALIASOK, s->s_mapclass.map_cflags))
276 {
277 syserr("setalias: map class %s can't handle aliases",
278 class);
279 }
280 else
281 {
282 map->map_class = &s->s_mapclass;
361 map->map_mflags |= MF_ALIAS;
362 if (map->map_class->map_parse(map, spec))
363 {
283 if (map->map_class->map_parse(map, spec))
284 {
364 map->map_mflags |= MF_VALID;
285 map->map_mflags |= MF_VALID|MF_ALIAS;
365 AliasFileMap->map_stack[NAliasFileMaps++] = map;
366 }
367 }
368 }
369}
286 AliasFileMap->map_stack[NAliasFileMaps++] = map;
287 }
288 }
289 }
290}
370/*
291 /*
371** ALIASWAIT -- wait for distinguished @:@ token to appear.
372**
373** This can decide to reopen or rebuild the alias file
374**
375** Parameters:
376** map -- a pointer to the map descriptor for this alias file.
377** ext -- the filename extension (e.g., ".db") for the
378** database file.
379** isopen -- if set, the database is already open, and we
380** should check for validity; otherwise, we are
381** just checking to see if it should be created.
382**
383** Returns:
292** ALIASWAIT -- wait for distinguished @:@ token to appear.
293**
294** This can decide to reopen or rebuild the alias file
295**
296** Parameters:
297** map -- a pointer to the map descriptor for this alias file.
298** ext -- the filename extension (e.g., ".db") for the
299** database file.
300** isopen -- if set, the database is already open, and we
301** should check for validity; otherwise, we are
302** just checking to see if it should be created.
303**
304** Returns:
384** true -- if the database is open when we return.
385** false -- if the database is closed when we return.
305** TRUE -- if the database is open when we return.
306** FALSE -- if the database is closed when we return.
386*/
387
388bool
389aliaswait(map, ext, isopen)
390 MAP *map;
391 char *ext;
307*/
308
309bool
310aliaswait(map, ext, isopen)
311 MAP *map;
312 char *ext;
392 bool isopen;
313 int isopen;
393{
314{
394 bool attimeout = false;
315 bool attimeout = FALSE;
395 time_t mtime;
396 struct stat stb;
316 time_t mtime;
317 struct stat stb;
397 char buf[MAXPATHLEN];
318 char buf[MAXNAME + 1];
398
399 if (tTd(27, 3))
319
320 if (tTd(27, 3))
400 sm_dprintf("aliaswait(%s:%s)\n",
401 map->map_class->map_cname, map->map_file);
321 printf("aliaswait(%s:%s)\n",
322 map->map_class->map_cname, map->map_file);
402 if (bitset(MF_ALIASWAIT, map->map_mflags))
403 return isopen;
404 map->map_mflags |= MF_ALIASWAIT;
405
406 if (SafeAlias > 0)
407 {
408 auto int st;
323 if (bitset(MF_ALIASWAIT, map->map_mflags))
324 return isopen;
325 map->map_mflags |= MF_ALIASWAIT;
326
327 if (SafeAlias > 0)
328 {
329 auto int st;
409 unsigned int sleeptime = 2;
410 unsigned int loopcount = 0; /* only used for debugging */
411 time_t toolong = curtime() + SafeAlias;
330 time_t toolong = curtime() + SafeAlias;
331 unsigned int sleeptime = 2;
412
413 while (isopen &&
414 map->map_class->map_lookup(map, "@", NULL, &st) == NULL)
415 {
416 if (curtime() > toolong)
417 {
418 /* we timed out */
332
333 while (isopen &&
334 map->map_class->map_lookup(map, "@", NULL, &st) == NULL)
335 {
336 if (curtime() > toolong)
337 {
338 /* we timed out */
419 attimeout = true;
339 attimeout = TRUE;
420 break;
421 }
422
423 /*
424 ** Close and re-open the alias database in case
425 ** the one is mv'ed instead of cp'ed in.
426 */
427
428 if (tTd(27, 2))
340 break;
341 }
342
343 /*
344 ** Close and re-open the alias database in case
345 ** the one is mv'ed instead of cp'ed in.
346 */
347
348 if (tTd(27, 2))
429 {
430 loopcount++;
431 sm_dprintf("aliaswait: sleeping for %u seconds (loopcount = %u)\n",
432 sleeptime, loopcount);
433 }
349 printf("aliaswait: sleeping for %d seconds\n",
350 sleeptime);
434
351
435 map->map_mflags |= MF_CLOSING;
436 map->map_class->map_close(map);
352 map->map_class->map_close(map);
437 map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
438 (void) sleep(sleeptime);
353 map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
354 sleep(sleeptime);
439 sleeptime *= 2;
440 if (sleeptime > 60)
441 sleeptime = 60;
442 isopen = map->map_class->map_open(map, O_RDONLY);
443 }
444 }
445
446 /* see if we need to go into auto-rebuild mode */
447 if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
448 {
449 if (tTd(27, 3))
355 sleeptime *= 2;
356 if (sleeptime > 60)
357 sleeptime = 60;
358 isopen = map->map_class->map_open(map, O_RDONLY);
359 }
360 }
361
362 /* see if we need to go into auto-rebuild mode */
363 if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
364 {
365 if (tTd(27, 3))
450 sm_dprintf("aliaswait: not rebuildable\n");
366 printf("aliaswait: not rebuildable\n");
451 map->map_mflags &= ~MF_ALIASWAIT;
452 return isopen;
453 }
454 if (stat(map->map_file, &stb) < 0)
455 {
456 if (tTd(27, 3))
367 map->map_mflags &= ~MF_ALIASWAIT;
368 return isopen;
369 }
370 if (stat(map->map_file, &stb) < 0)
371 {
372 if (tTd(27, 3))
457 sm_dprintf("aliaswait: no source file\n");
373 printf("aliaswait: no source file\n");
458 map->map_mflags &= ~MF_ALIASWAIT;
459 return isopen;
460 }
461 mtime = stb.st_mtime;
374 map->map_mflags &= ~MF_ALIASWAIT;
375 return isopen;
376 }
377 mtime = stb.st_mtime;
462 if (sm_strlcpyn(buf, sizeof(buf), 2,
463 map->map_file, ext == NULL ? "" : ext) >= sizeof(buf))
464 {
465 if (LogLevel > 3)
466 sm_syslog(LOG_INFO, NOQID,
467 "alias database %s%s name too long",
468 map->map_file, ext == NULL ? "" : ext);
469 message("alias database %s%s name too long",
470 map->map_file, ext == NULL ? "" : ext);
471 }
472
378 snprintf(buf, sizeof buf, "%s%s",
379 map->map_file, ext == NULL ? "" : ext);
473 if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || attimeout)
474 {
380 if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || attimeout)
381 {
475 if (LogLevel > 3)
476 sm_syslog(LOG_INFO, NOQID,
477 "alias database %s out of date", buf);
478 message("Warning: alias database %s out of date", buf);
382 /* database is out of date */
383 if (AutoRebuild && stb.st_ino != 0 &&
384 (stb.st_uid == geteuid() ||
385 (geteuid() == 0 && stb.st_uid == TrustedFileUid)))
386 {
387 bool oldSuprErrs;
388
389 message("auto-rebuilding alias database %s", buf);
390 oldSuprErrs = SuprErrs;
391 SuprErrs = TRUE;
392 if (isopen)
393 {
394 map->map_class->map_close(map);
395 map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
396 }
397 (void) rebuildaliases(map, TRUE);
398 isopen = map->map_class->map_open(map, O_RDONLY);
399 SuprErrs = oldSuprErrs;
400 }
401 else
402 {
403 if (LogLevel > 3)
404 sm_syslog(LOG_INFO, NOQID,
405 "alias database %s out of date",
406 buf);
407 message("Warning: alias database %s out of date", buf);
408 }
479 }
480 map->map_mflags &= ~MF_ALIASWAIT;
481 return isopen;
482}
409 }
410 map->map_mflags &= ~MF_ALIASWAIT;
411 return isopen;
412}
483/*
413 /*
484** REBUILDALIASES -- rebuild the alias database.
485**
486** Parameters:
487** map -- the database to rebuild.
488** automatic -- set if this was automatically generated.
489**
490** Returns:
414** REBUILDALIASES -- rebuild the alias database.
415**
416** Parameters:
417** map -- the database to rebuild.
418** automatic -- set if this was automatically generated.
419**
420** Returns:
491** true if successful; false otherwise.
421** TRUE if successful; FALSE otherwise.
492**
493** Side Effects:
494** Reads the text version of the database, builds the
495** DBM or DB version.
496*/
497
498bool
499rebuildaliases(map, automatic)
500 register MAP *map;
501 bool automatic;
502{
422**
423** Side Effects:
424** Reads the text version of the database, builds the
425** DBM or DB version.
426*/
427
428bool
429rebuildaliases(map, automatic)
430 register MAP *map;
431 bool automatic;
432{
503 SM_FILE_T *af;
504 bool nolock = false;
505 bool success = false;
506 long sff = SFF_OPENASROOT|SFF_REGONLY|SFF_NOLOCK;
433 FILE *af;
434 bool nolock = FALSE;
435 bool success = FALSE;
436 int sff = SFF_OPENASROOT|SFF_REGONLY|SFF_NOLOCK;
507 sigfunc_t oldsigint, oldsigquit;
508#ifdef SIGTSTP
509 sigfunc_t oldsigtstp;
437 sigfunc_t oldsigint, oldsigquit;
438#ifdef SIGTSTP
439 sigfunc_t oldsigtstp;
510#endif /* SIGTSTP */
440#endif
511
512 if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
441
442 if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
513 return false;
443 return FALSE;
514
444
515 if (!bitnset(DBS_LINKEDALIASFILEINWRITABLEDIR, DontBlameSendmail))
445 if (!bitset(DBS_LINKEDALIASFILEINWRITABLEDIR, DontBlameSendmail))
516 sff |= SFF_NOWLINK;
446 sff |= SFF_NOWLINK;
517 if (!bitnset(DBS_GROUPWRITABLEALIASFILE, DontBlameSendmail))
447 if (!bitset(DBS_GROUPWRITABLEALIASFILE, DontBlameSendmail))
518 sff |= SFF_NOGWFILES;
448 sff |= SFF_NOGWFILES;
519 if (!bitnset(DBS_WORLDWRITABLEALIASFILE, DontBlameSendmail))
449 if (!bitset(DBS_WORLDWRITABLEALIASFILE, DontBlameSendmail))
520 sff |= SFF_NOWWFILES;
521
522 /* try to lock the source file */
523 if ((af = safefopen(map->map_file, O_RDWR, 0, sff)) == NULL)
524 {
525 struct stat stb;
526
527 if ((errno != EACCES && errno != EROFS) || automatic ||
528 (af = safefopen(map->map_file, O_RDONLY, 0, sff)) == NULL)
529 {
530 int saveerr = errno;
531
532 if (tTd(27, 1))
450 sff |= SFF_NOWWFILES;
451
452 /* try to lock the source file */
453 if ((af = safefopen(map->map_file, O_RDWR, 0, sff)) == NULL)
454 {
455 struct stat stb;
456
457 if ((errno != EACCES && errno != EROFS) || automatic ||
458 (af = safefopen(map->map_file, O_RDONLY, 0, sff)) == NULL)
459 {
460 int saveerr = errno;
461
462 if (tTd(27, 1))
533 sm_dprintf("Can't open %s: %s\n",
534 map->map_file, sm_errstring(saveerr));
463 printf("Can't open %s: %s\n",
464 map->map_file, errstring(saveerr));
535 if (!automatic && !bitset(MF_OPTIONAL, map->map_mflags))
536 message("newaliases: cannot open %s: %s",
465 if (!automatic && !bitset(MF_OPTIONAL, map->map_mflags))
466 message("newaliases: cannot open %s: %s",
537 map->map_file, sm_errstring(saveerr));
467 map->map_file, errstring(saveerr));
538 errno = 0;
468 errno = 0;
539 return false;
469 return FALSE;
540 }
470 }
541 nolock = true;
471 nolock = TRUE;
542 if (tTd(27, 1) ||
472 if (tTd(27, 1) ||
543 fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &stb) < 0 ||
473 fstat(fileno(af), &stb) < 0 ||
544 bitset(S_IWUSR|S_IWGRP|S_IWOTH, stb.st_mode))
545 message("warning: cannot lock %s: %s",
474 bitset(S_IWUSR|S_IWGRP|S_IWOTH, stb.st_mode))
475 message("warning: cannot lock %s: %s",
546 map->map_file, sm_errstring(errno));
476 map->map_file, errstring(errno));
547 }
548
549 /* see if someone else is rebuilding the alias file */
550 if (!nolock &&
477 }
478
479 /* see if someone else is rebuilding the alias file */
480 if (!nolock &&
551 !lockfile(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), map->map_file,
552 NULL, LOCK_EX|LOCK_NB))
481 !lockfile(fileno(af), map->map_file, NULL, LOCK_EX|LOCK_NB))
553 {
554 /* yes, they are -- wait until done */
555 message("Alias file %s is locked (maybe being rebuilt)",
556 map->map_file);
557 if (OpMode != MD_INITALIAS)
558 {
559 /* wait for other rebuild to complete */
482 {
483 /* yes, they are -- wait until done */
484 message("Alias file %s is locked (maybe being rebuilt)",
485 map->map_file);
486 if (OpMode != MD_INITALIAS)
487 {
488 /* wait for other rebuild to complete */
560 (void) lockfile(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL),
561 map->map_file, NULL, LOCK_EX);
489 (void) lockfile(fileno(af), map->map_file, NULL,
490 LOCK_EX);
562 }
491 }
563 (void) sm_io_close(af, SM_TIME_DEFAULT);
492 (void) xfclose(af, "rebuildaliases1", map->map_file);
564 errno = 0;
493 errno = 0;
565 return false;
494 return FALSE;
566 }
567
495 }
496
568 oldsigint = sm_signal(SIGINT, SIG_IGN);
569 oldsigquit = sm_signal(SIGQUIT, SIG_IGN);
497 oldsigint = setsignal(SIGINT, SIG_IGN);
498 oldsigquit = setsignal(SIGQUIT, SIG_IGN);
570#ifdef SIGTSTP
499#ifdef SIGTSTP
571 oldsigtstp = sm_signal(SIGTSTP, SIG_IGN);
572#endif /* SIGTSTP */
500 oldsigtstp = setsignal(SIGTSTP, SIG_IGN);
501#endif
573
574 if (map->map_class->map_open(map, O_RDWR))
575 {
576 if (LogLevel > 7)
577 {
578 sm_syslog(LOG_NOTICE, NOQID,
579 "alias database %s %srebuilt by %s",
580 map->map_file, automatic ? "auto" : "",
581 username());
582 }
583 map->map_mflags |= MF_OPEN|MF_WRITABLE;
502
503 if (map->map_class->map_open(map, O_RDWR))
504 {
505 if (LogLevel > 7)
506 {
507 sm_syslog(LOG_NOTICE, NOQID,
508 "alias database %s %srebuilt by %s",
509 map->map_file, automatic ? "auto" : "",
510 username());
511 }
512 map->map_mflags |= MF_OPEN|MF_WRITABLE;
584 map->map_pid = CurrentPid;
585 readaliases(map, af, !automatic, true);
586 success = true;
513 readaliases(map, af, !automatic, TRUE);
514 success = TRUE;
587 }
588 else
589 {
590 if (tTd(27, 1))
515 }
516 else
517 {
518 if (tTd(27, 1))
591 sm_dprintf("Can't create database for %s: %s\n",
592 map->map_file, sm_errstring(errno));
519 printf("Can't create database for %s: %s\n",
520 map->map_file, errstring(errno));
593 if (!automatic)
594 syserr("Cannot create database for alias file %s",
595 map->map_file);
596 }
597
598 /* close the file, thus releasing locks */
521 if (!automatic)
522 syserr("Cannot create database for alias file %s",
523 map->map_file);
524 }
525
526 /* close the file, thus releasing locks */
599 (void) sm_io_close(af, SM_TIME_DEFAULT);
527 xfclose(af, "rebuildaliases2", map->map_file);
600
601 /* add distinguished entries and close the database */
602 if (bitset(MF_OPEN, map->map_mflags))
603 {
528
529 /* add distinguished entries and close the database */
530 if (bitset(MF_OPEN, map->map_mflags))
531 {
604 map->map_mflags |= MF_CLOSING;
605 map->map_class->map_close(map);
532 map->map_class->map_close(map);
606 map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
533 map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
607 }
608
609 /* restore the old signals */
534 }
535
536 /* restore the old signals */
610 (void) sm_signal(SIGINT, oldsigint);
611 (void) sm_signal(SIGQUIT, oldsigquit);
537 (void) setsignal(SIGINT, oldsigint);
538 (void) setsignal(SIGQUIT, oldsigquit);
612#ifdef SIGTSTP
539#ifdef SIGTSTP
613 (void) sm_signal(SIGTSTP, oldsigtstp);
614#endif /* SIGTSTP */
540 (void) setsignal(SIGTSTP, oldsigtstp);
541#endif
615 return success;
616}
542 return success;
543}
617/*
544 /*
618** READALIASES -- read and process the alias file.
619**
620** This routine implements the part of initaliases that occurs
621** when we are not going to use the DBM stuff.
622**
623** Parameters:
624** map -- the alias database descriptor.
625** af -- file to read the aliases from.
545** READALIASES -- read and process the alias file.
546**
547** This routine implements the part of initaliases that occurs
548** when we are not going to use the DBM stuff.
549**
550** Parameters:
551** map -- the alias database descriptor.
552** af -- file to read the aliases from.
626** announcestats -- announce statistics regarding number of
553** announcestats -- anounce statistics regarding number of
627** aliases, longest alias, etc.
628** logstats -- lot the same info.
629**
630** Returns:
631** none.
632**
633** Side Effects:
634** Reads aliasfile into the symbol table.
635** Optionally, builds the .dir & .pag files.
636*/
637
638void
639readaliases(map, af, announcestats, logstats)
640 register MAP *map;
554** aliases, longest alias, etc.
555** logstats -- lot the same info.
556**
557** Returns:
558** none.
559**
560** Side Effects:
561** Reads aliasfile into the symbol table.
562** Optionally, builds the .dir & .pag files.
563*/
564
565void
566readaliases(map, af, announcestats, logstats)
567 register MAP *map;
641 SM_FILE_T *af;
568 FILE *af;
642 bool announcestats;
643 bool logstats;
644{
645 register char *p;
646 char *rhs;
647 bool skipping;
648 long naliases, bytes, longest;
649 ADDRESS al, bl;
650 char line[BUFSIZ];
651
652 /*
653 ** Read and interpret lines
654 */
655
656 FileName = map->map_file;
657 LineNumber = 0;
658 naliases = bytes = longest = 0;
569 bool announcestats;
570 bool logstats;
571{
572 register char *p;
573 char *rhs;
574 bool skipping;
575 long naliases, bytes, longest;
576 ADDRESS al, bl;
577 char line[BUFSIZ];
578
579 /*
580 ** Read and interpret lines
581 */
582
583 FileName = map->map_file;
584 LineNumber = 0;
585 naliases = bytes = longest = 0;
659 skipping = false;
660 while (sm_io_fgets(af, SM_TIME_DEFAULT, line, sizeof(line)) >= 0)
586 skipping = FALSE;
587 while (fgets(line, sizeof (line), af) != NULL)
661 {
662 int lhssize, rhssize;
663 int c;
664
665 LineNumber++;
666 p = strchr(line, '\n');
588 {
589 int lhssize, rhssize;
590 int c;
591
592 LineNumber++;
593 p = strchr(line, '\n');
667
668 /* XXX what if line="a\\" ? */
594#if _FFR_BACKSLASH_IN_ALIASES
669 while (p != NULL && p > line && p[-1] == '\\')
670 {
671 p--;
595 while (p != NULL && p > line && p[-1] == '\\')
596 {
597 p--;
672 if (sm_io_fgets(af, SM_TIME_DEFAULT, p,
673 SPACELEFT(line, p)) < 0)
598 if (fgets(p, SPACELEFT(line, p), af) == NULL)
674 break;
675 LineNumber++;
676 p = strchr(p, '\n');
677 }
599 break;
600 LineNumber++;
601 p = strchr(p, '\n');
602 }
603#endif
678 if (p != NULL)
679 *p = '\0';
604 if (p != NULL)
605 *p = '\0';
680 else if (!sm_io_eof(af))
606 else if (!feof(af))
681 {
607 {
682 errno = 0;
683 syserr("554 5.3.0 alias line too long");
608 syserr("554 alias line too long");
684
685 /* flush to end of line */
609
610 /* flush to end of line */
686 while ((c = sm_io_getc(af, SM_TIME_DEFAULT)) !=
687 SM_IO_EOF && c != '\n')
611 while ((c = getc(af)) != EOF && c != '\n')
688 continue;
689
690 /* skip any continuation lines */
612 continue;
613
614 /* skip any continuation lines */
691 skipping = true;
615 skipping = TRUE;
692 continue;
693 }
694 switch (line[0])
695 {
696 case '#':
697 case '\0':
616 continue;
617 }
618 switch (line[0])
619 {
620 case '#':
621 case '\0':
698 skipping = false;
622 skipping = FALSE;
699 continue;
700
701 case ' ':
702 case '\t':
703 if (!skipping)
623 continue;
624
625 case ' ':
626 case '\t':
627 if (!skipping)
704 syserr("554 5.3.5 Non-continuation line starts with space");
705 skipping = true;
628 syserr("554 Non-continuation line starts with space");
629 skipping = TRUE;
706 continue;
707 }
630 continue;
631 }
708 skipping = false;
632 skipping = FALSE;
709
710 /*
711 ** Process the LHS
712 ** Find the colon separator, and parse the address.
713 ** It should resolve to a local name -- this will
714 ** be checked later (we want to optionally do
715 ** parsing of the RHS first to maximize error
716 ** detection).
717 */
718
719 for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++)
720 continue;
721 if (*p++ != ':')
722 {
633
634 /*
635 ** Process the LHS
636 ** Find the colon separator, and parse the address.
637 ** It should resolve to a local name -- this will
638 ** be checked later (we want to optionally do
639 ** parsing of the RHS first to maximize error
640 ** detection).
641 */
642
643 for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++)
644 continue;
645 if (*p++ != ':')
646 {
723 syserr("554 5.3.5 missing colon");
647 syserr("554 missing colon");
724 continue;
725 }
648 continue;
649 }
726 if (parseaddr(line, &al, RF_COPYALL, ':', NULL, CurEnv, true)
727 == NULL)
650 if (parseaddr(line, &al, RF_COPYALL, ':', NULL, CurEnv) == NULL)
728 {
651 {
729 syserr("554 5.3.5 %.40s... illegal alias name", line);
652 syserr("554 %.40s... illegal alias name", line);
730 continue;
731 }
732
733 /*
734 ** Process the RHS.
735 ** 'al' is the internal form of the LHS address.
736 ** 'p' points to the text of the RHS.
737 */
738
739 while (isascii(*p) && isspace(*p))
740 p++;
741 rhs = p;
742 for (;;)
743 {
744 register char *nlp;
745
746 nlp = &p[strlen(p)];
653 continue;
654 }
655
656 /*
657 ** Process the RHS.
658 ** 'al' is the internal form of the LHS address.
659 ** 'p' points to the text of the RHS.
660 */
661
662 while (isascii(*p) && isspace(*p))
663 p++;
664 rhs = p;
665 for (;;)
666 {
667 register char *nlp;
668
669 nlp = &p[strlen(p)];
747 if (nlp > p && nlp[-1] == '\n')
670 if (nlp[-1] == '\n')
748 *--nlp = '\0';
749
750 if (CheckAliases)
751 {
752 /* do parsing & compression of addresses */
753 while (*p != '\0')
754 {
755 auto char *delimptr;
756
757 while ((isascii(*p) && isspace(*p)) ||
758 *p == ',')
759 p++;
760 if (*p == '\0')
761 break;
762 if (parseaddr(p, &bl, RF_COPYNONE, ',',
671 *--nlp = '\0';
672
673 if (CheckAliases)
674 {
675 /* do parsing & compression of addresses */
676 while (*p != '\0')
677 {
678 auto char *delimptr;
679
680 while ((isascii(*p) && isspace(*p)) ||
681 *p == ',')
682 p++;
683 if (*p == '\0')
684 break;
685 if (parseaddr(p, &bl, RF_COPYNONE, ',',
763 &delimptr, CurEnv, true)
764 == NULL)
765 usrerr("553 5.3.5 %s... bad address", p);
686 &delimptr, CurEnv) == NULL)
687 usrerr("553 %s... bad address", p);
766 p = delimptr;
767 }
768 }
769 else
770 {
771 p = nlp;
772 }
773
774 /* see if there should be a continuation line */
688 p = delimptr;
689 }
690 }
691 else
692 {
693 p = nlp;
694 }
695
696 /* see if there should be a continuation line */
775 c = sm_io_getc(af, SM_TIME_DEFAULT);
776 if (!sm_io_eof(af))
777 (void) sm_io_ungetc(af, SM_TIME_DEFAULT, c);
697 c = getc(af);
698 if (!feof(af))
699 (void) ungetc(c, af);
778 if (c != ' ' && c != '\t')
779 break;
780
781 /* read continuation line */
700 if (c != ' ' && c != '\t')
701 break;
702
703 /* read continuation line */
782 if (sm_io_fgets(af, SM_TIME_DEFAULT, p,
783 sizeof(line) - (p-line)) < 0)
704 if (fgets(p, sizeof line - (p - line), af) == NULL)
784 break;
785 LineNumber++;
786
787 /* check for line overflow */
705 break;
706 LineNumber++;
707
708 /* check for line overflow */
788 if (strchr(p, '\n') == NULL && !sm_io_eof(af))
709 if (strchr(p, '\n') == NULL && !feof(af))
789 {
710 {
790 usrerr("554 5.3.5 alias too long");
791 while ((c = sm_io_getc(af, SM_TIME_DEFAULT))
792 != SM_IO_EOF && c != '\n')
711 usrerr("554 alias too long");
712 while ((c = fgetc(af)) != EOF && c != '\n')
793 continue;
713 continue;
794 skipping = true;
714 skipping = TRUE;
795 break;
796 }
797 }
798
799 if (skipping)
800 continue;
801
802 if (!bitnset(M_ALIASABLE, al.q_mailer->m_flags))
803 {
715 break;
716 }
717 }
718
719 if (skipping)
720 continue;
721
722 if (!bitnset(M_ALIASABLE, al.q_mailer->m_flags))
723 {
804 syserr("554 5.3.5 %s... cannot alias non-local names",
724 syserr("554 %s... cannot alias non-local names",
805 al.q_paddr);
806 continue;
807 }
808
809 /*
810 ** Insert alias into symbol table or database file.
811 **
812 ** Special case pOStmaStER -- always make it lower case.
813 */
814
725 al.q_paddr);
726 continue;
727 }
728
729 /*
730 ** Insert alias into symbol table or database file.
731 **
732 ** Special case pOStmaStER -- always make it lower case.
733 */
734
815 if (sm_strcasecmp(al.q_user, "postmaster") == 0)
735 if (strcasecmp(al.q_user, "postmaster") == 0)
816 makelower(al.q_user);
817
818 lhssize = strlen(al.q_user);
819 rhssize = strlen(rhs);
736 makelower(al.q_user);
737
738 lhssize = strlen(al.q_user);
739 rhssize = strlen(rhs);
820 if (rhssize > 0)
821 {
822 /* is RHS empty (just spaces)? */
823 p = rhs;
824 while (isascii(*p) && isspace(*p))
825 p++;
826 }
827 if (rhssize == 0 || *p == '\0')
828 {
829 syserr("554 5.3.5 %.40s... missing value for alias",
830 line);
740 map->map_class->map_store(map, al.q_user, rhs);
831
741
832 }
833 else
834 {
835 map->map_class->map_store(map, al.q_user, rhs);
836
837 /* statistics */
838 naliases++;
839 bytes += lhssize + rhssize;
840 if (rhssize > longest)
841 longest = rhssize;
842 }
843
844#if 0
845 /*
846 ** address strings are now stored in the envelope rpool,
847 ** and therefore cannot be freed.
848 */
849 if (al.q_paddr != NULL)
742 if (al.q_paddr != NULL)
850 sm_free(al.q_paddr); /* disabled */
743 free(al.q_paddr);
851 if (al.q_host != NULL)
744 if (al.q_host != NULL)
852 sm_free(al.q_host); /* disabled */
745 free(al.q_host);
853 if (al.q_user != NULL)
746 if (al.q_user != NULL)
854 sm_free(al.q_user); /* disabled */
855#endif /* 0 */
747 free(al.q_user);
748
749 /* statistics */
750 naliases++;
751 bytes += lhssize + rhssize;
752 if (rhssize > longest)
753 longest = rhssize;
856 }
857
858 CurEnv->e_to = NULL;
859 FileName = NULL;
860 if (Verbose || announcestats)
754 }
755
756 CurEnv->e_to = NULL;
757 FileName = NULL;
758 if (Verbose || announcestats)
861 message("%s: %ld aliases, longest %ld bytes, %ld bytes total",
759 message("%s: %d aliases, longest %d bytes, %d bytes total",
862 map->map_file, naliases, longest, bytes);
863 if (LogLevel > 7 && logstats)
864 sm_syslog(LOG_INFO, NOQID,
760 map->map_file, naliases, longest, bytes);
761 if (LogLevel > 7 && logstats)
762 sm_syslog(LOG_INFO, NOQID,
865 "%s: %ld aliases, longest %ld bytes, %ld bytes total",
763 "%s: %d aliases, longest %d bytes, %d bytes total",
866 map->map_file, naliases, longest, bytes);
867}
764 map->map_file, naliases, longest, bytes);
765}
868/*
766 /*
869** FORWARD -- Try to forward mail
870**
871** This is similar but not identical to aliasing.
872**
873** Parameters:
874** user -- the name of the user who's mail we would like
875** to forward to. It must have been verified --
876** i.e., the q_home field must have been filled

--- 17 unchanged lines hidden (view full) ---

894 int aliaslevel;
895 register ENVELOPE *e;
896{
897 char *pp;
898 char *ep;
899 bool got_transient;
900
901 if (tTd(27, 1))
767** FORWARD -- Try to forward mail
768**
769** This is similar but not identical to aliasing.
770**
771** Parameters:
772** user -- the name of the user who's mail we would like
773** to forward to. It must have been verified --
774** i.e., the q_home field must have been filled

--- 17 unchanged lines hidden (view full) ---

792 int aliaslevel;
793 register ENVELOPE *e;
794{
795 char *pp;
796 char *ep;
797 bool got_transient;
798
799 if (tTd(27, 1))
902 sm_dprintf("forward(%s)\n", user->q_paddr);
800 printf("forward(%s)\n", user->q_paddr);
903
904 if (!bitnset(M_HASPWENT, user->q_mailer->m_flags) ||
801
802 if (!bitnset(M_HASPWENT, user->q_mailer->m_flags) ||
905 !QS_IS_OK(user->q_state))
803 bitset(QBADADDR, user->q_flags))
906 return;
804 return;
907 if (ForwardPath != NULL && *ForwardPath == '\0')
908 return;
909 if (user->q_home == NULL)
910 {
805 if (user->q_home == NULL)
806 {
911 syserr("554 5.3.0 forward: no home");
807 syserr("554 forward: no home");
912 user->q_home = "/no/such/directory";
913 }
914
915 /* good address -- look for .forward file in home */
808 user->q_home = "/no/such/directory";
809 }
810
811 /* good address -- look for .forward file in home */
916 macdefine(&e->e_macro, A_PERM, 'z', user->q_home);
917 macdefine(&e->e_macro, A_PERM, 'u', user->q_user);
918 macdefine(&e->e_macro, A_PERM, 'h', user->q_host);
812 define('z', user->q_home, e);
813 define('u', user->q_user, e);
814 define('h', user->q_host, e);
919 if (ForwardPath == NULL)
920 ForwardPath = newstr("\201z/.forward");
921
815 if (ForwardPath == NULL)
816 ForwardPath = newstr("\201z/.forward");
817
922 got_transient = false;
818 got_transient = FALSE;
923 for (pp = ForwardPath; pp != NULL; pp = ep)
924 {
925 int err;
819 for (pp = ForwardPath; pp != NULL; pp = ep)
820 {
821 int err;
926 char buf[MAXPATHLEN];
927 struct stat st;
822 char buf[MAXPATHLEN+1];
928
823
929 ep = strchr(pp, SEPARATOR);
824 ep = strchr(pp, ':');
930 if (ep != NULL)
931 *ep = '\0';
825 if (ep != NULL)
826 *ep = '\0';
932 expand(pp, buf, sizeof(buf), e);
827 expand(pp, buf, sizeof buf, e);
933 if (ep != NULL)
828 if (ep != NULL)
934 *ep++ = SEPARATOR;
829 *ep++ = ':';
935 if (buf[0] == '\0')
936 continue;
937 if (tTd(27, 3))
830 if (buf[0] == '\0')
831 continue;
832 if (tTd(27, 3))
938 sm_dprintf("forward: trying %s\n", buf);
833 printf("forward: trying %s\n", buf);
939
834
940 err = include(buf, true, user, sendq, aliaslevel, e);
835 err = include(buf, TRUE, user, sendq, aliaslevel, e);
941 if (err == 0)
942 break;
943 else if (transienterror(err))
944 {
945 /* we may have to suspend this message */
836 if (err == 0)
837 break;
838 else if (transienterror(err))
839 {
840 /* we may have to suspend this message */
946 got_transient = true;
841 got_transient = TRUE;
947 if (tTd(27, 2))
842 if (tTd(27, 2))
948 sm_dprintf("forward: transient error on %s\n",
949 buf);
843 printf("forward: transient error on %s\n", buf);
950 if (LogLevel > 2)
844 if (LogLevel > 2)
951 {
952 char *curhost = CurHostName;
953
954 CurHostName = NULL;
955 sm_syslog(LOG_ERR, e->e_id,
845 sm_syslog(LOG_ERR, e->e_id,
956 "forward %s: transient error: %s",
957 buf, sm_errstring(err));
958 CurHostName = curhost;
959 }
960
846 "forward %s: transient error: %s",
847 buf, errstring(err));
961 }
962 else
963 {
964 switch (err)
965 {
966 case ENOENT:
967 break;
968
848 }
849 else
850 {
851 switch (err)
852 {
853 case ENOENT:
854 break;
855
969 case E_SM_WWDIR:
970 case E_SM_GWDIR:
971 /* check if it even exists */
972 if (stat(buf, &st) < 0 && errno == ENOENT)
973 {
974 if (bitnset(DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH,
975 DontBlameSendmail))
976 break;
977 }
978 /* FALLTHROUGH */
979
980#if _FFR_FORWARD_SYSERR
981 case E_SM_NOSLINK:
982 case E_SM_NOHLINK:
983 case E_SM_REGONLY:
984 case E_SM_ISEXEC:
856#if _FFR_FORWARD_SYSERR
857 case E_SM_NOSLINK:
858 case E_SM_NOHLINK:
859 case E_SM_REGONLY:
860 case E_SM_ISEXEC:
861 case E_SM_WWDIR:
862 case E_SM_GWDIR:
985 case E_SM_WWFILE:
986 case E_SM_GWFILE:
863 case E_SM_WWFILE:
864 case E_SM_GWFILE:
987 syserr("forward: %s: %s", buf, sm_errstring(err));
865 syserr("forward: %s: %s", buf, errstring(err));
988 break;
866 break;
989#endif /* _FFR_FORWARD_SYSERR */
867#endif
990
991 default:
992 if (LogLevel > (RunAsUid == 0 ? 2 : 10))
993 sm_syslog(LOG_WARNING, e->e_id,
868
869 default:
870 if (LogLevel > (RunAsUid == 0 ? 2 : 10))
871 sm_syslog(LOG_WARNING, e->e_id,
994 "forward %s: %s", buf,
995 sm_errstring(err));
872 "forward %s: %s", buf,
873 errstring(err));
996 if (Verbose)
997 message("forward: %s: %s",
874 if (Verbose)
875 message("forward: %s: %s",
998 buf, sm_errstring(err));
876 buf,
877 errstring(err));
999 break;
1000 }
1001 }
1002 }
1003 if (pp == NULL && got_transient)
1004 {
1005 /*
1006 ** There was no successful .forward open and at least one
1007 ** transient open. We have to defer this address for
1008 ** further delivery.
1009 */
1010
1011 message("transient .forward open error: message queued");
878 break;
879 }
880 }
881 }
882 if (pp == NULL && got_transient)
883 {
884 /*
885 ** There was no successful .forward open and at least one
886 ** transient open. We have to defer this address for
887 ** further delivery.
888 */
889
890 message("transient .forward open error: message queued");
1012 user->q_state = QS_QUEUEUP;
891 user->q_flags |= QQUEUEUP;
1013 return;
1014 }
1015}
892 return;
893 }
894}