set QDONTSEND together with QBADADDR
[unix-history] / usr / src / usr.sbin / sendmail / src / recipient.c
CommitLineData
b2a81223 1/*
dc45ba8c 2 * Copyright (c) 1983 Eric P. Allman
bee79b64
KB
3 * Copyright (c) 1988 Regents of the University of California.
4 * All rights reserved.
5 *
417f7a11 6 * %sccs.include.redist.c%
bee79b64 7 */
b2a81223
DF
8
9#ifndef lint
4aa5a536 10static char sccsid[] = "@(#)recipient.c 6.23 (Berkeley) %G%";
bee79b64 11#endif /* not lint */
b2a81223 12
72041f93 13# include "sendmail.h"
611050b6 14# include <sys/stat.h>
f9344236 15# include <fcntl.h>
6eefe4f6 16# include <pwd.h>
6eefe4f6 17
6eefe4f6 18/*
811a6cf3 19** SENDTOLIST -- Designate a send list.
6eefe4f6
EA
20**
21** The parameter is a comma-separated list of people to send to.
22** This routine arranges to send to all of them.
23**
abae7b2d
EA
24** The `ctladdr' is the address that expanded to be this one,
25** e.g., in an alias expansion. This is used for a number of
26** purposed, most notably inheritance of uid/gid for protection
27** purposes. It is also used to detect self-reference in group
28** expansions and the like.
29**
6eefe4f6
EA
30** Parameters:
31** list -- the send list.
1bf7c76b
EA
32** ctladdr -- the address template for the person to
33** send to -- effective uid/gid are important.
d4f42161
EA
34** This is typically the alias that caused this
35** expansion.
36** sendq -- a pointer to the head of a queue to put
37** these people into.
118e6693 38** e -- the envelope in which to add these recipients.
abae7b2d 39** qflags -- special flags to set in the q_flags field.
6eefe4f6
EA
40**
41** Returns:
abae7b2d 42** pointer to chain of addresses.
6eefe4f6
EA
43**
44** Side Effects:
45** none.
46*/
47
48# define MAXRCRSN 10
49
abae7b2d
EA
50ADDRESS *
51sendto(list, copyf, ctladdr, qflags)
6eefe4f6 52 char *list;
1bf7c76b 53 ADDRESS *ctladdr;
4e5e456f 54 ADDRESS **sendq;
a4076aed 55 register ENVELOPE *e;
abae7b2d 56 u_short qflags;
6eefe4f6
EA
57{
58 register char *p;
7b955214 59 register ADDRESS *al; /* list of addresses to send to */
92f12b98 60 bool firstone; /* set on first address sent */
d3f52e20 61 char delimiter; /* the address delimiter */
1c7897ef 62 int naddrs;
abae7b2d
EA
63 ADDRESS *sibl; /* sibling pointer in tree */
64 ADDRESS *prev; /* previous sibling */
d6b27179 65
9678c96d 66 if (tTd(25, 1))
331b7c9f
EA
67 {
68 printf("sendto: %s\n ctladdr=", list);
69 printaddr(ctladdr, FALSE);
70 }
6eefe4f6 71
7b955214 72 /* heuristic to determine old versus new style addresses */
a2983993 73 if (ctladdr == NULL &&
f3d8f6d6
EA
74 (strchr(list, ',') != NULL || strchr(list, ';') != NULL ||
75 strchr(list, '<') != NULL || strchr(list, '(') != NULL))
a4076aed 76 e->e_flags &= ~EF_OLDSTYLE;
d3f52e20 77 delimiter = ' ';
a4076aed 78 if (!bitset(EF_OLDSTYLE, e->e_flags) || ctladdr != NULL)
d3f52e20 79 delimiter = ',';
7b955214 80
92f12b98 81 firstone = TRUE;
d6b27179 82 al = NULL;
1c7897ef 83 naddrs = 0;
7b955214 84
506fc377 85 for (p = list; *p != '\0'; )
6eefe4f6 86 {
9e2cf26f 87 auto char *delimptr;
506fc377 88 register ADDRESS *a;
6eefe4f6
EA
89
90 /* parse the address */
2bee003d 91 while ((isascii(*p) && isspace(*p)) || *p == ',')
506fc377 92 p++;
9e2cf26f
EA
93 a = parseaddr(p, (ADDRESS *) NULL, 1, delimiter, &delimptr, e);
94 p = delimptr;
b9fadd5b
EA
95 if (a == NULL)
96 continue;
d6b27179 97 a->q_next = al;
1bf7c76b 98 a->q_alias = ctladdr;
abae7b2d
EA
99 if (ctladdr != NULL)
100 a->q_flags |= ctladdr->q_flags & ~QPRIMARY;
101 a->q_flags |= qflags;
331b7c9f
EA
102
103 /* see if this should be marked as a primary address */
92f12b98 104 if (ctladdr == NULL ||
506fc377 105 (firstone && *p == '\0' && bitset(QPRIMARY, ctladdr->q_flags)))
92f12b98 106 a->q_flags |= QPRIMARY;
331b7c9f 107
7338e3d4 108 if (ctladdr != NULL && sameaddr(ctladdr, a))
5d41b806 109 ctladdr->q_flags |= QSELFREF;
78bbbc48 110 al = a;
92f12b98 111 firstone = FALSE;
d6b27179
EA
112 }
113
114 /* arrange to send to everyone on the local send list */
abae7b2d
EA
115 prev = sibl = NULL;
116 if (ctladdr != NULL)
117 prev = ctladdr->q_child;
d6b27179
EA
118 while (al != NULL)
119 {
120 register ADDRESS *a = al;
abae7b2d 121 extern ADDRESS *recipient();
d344c0b7 122 extern ADDRESS *recipient();
d6b27179
EA
123
124 al = a->q_next;
abae7b2d
EA
125 sibl = recipient(a);
126 if (sibl != NULL)
127 {
128 extern ADDRESS *addrref();
129
130 /* inherit full name */
131 if (sibl->q_fullname == NULL && ctladdr != NULL)
132 sibl->q_fullname = ctladdr->q_fullname;
133
134 /* link tree together (but only if the node is new) */
135 if (sibl == a)
136 {
137 sibl->q_sibling = prev;
138 prev = sibl;
139 }
140 }
6eefe4f6 141 }
d6b27179 142
a4076aed 143 e->e_to = NULL;
1c7897ef 144 return (naddrs);
abae7b2d
EA
145 if (ctladdr != NULL)
146 ctladdr->q_child = prev;
147 return (prev);
148}
149\f/*
150** ADDRREF -- return pointer to address that references another address.
151**
152** Parameters:
153** a -- address to check.
154** r -- reference to find.
155**
156** Returns:
157** address of node in tree rooted at 'a' that references
158** 'r'.
159** NULL if no such node exists.
160**
161** Side Effects:
162** none.
163*/
164
165ADDRESS *
166addrref(a, r)
167 register ADDRESS *a;
168 register ADDRESS *r;
169{
170 register ADDRESS *q;
171
172 while (a != NULL)
173 {
174 if (a->q_child == r || a->q_sibling == r)
175 return (a);
176 q = addrref(a->q_child, r);
177 if (q != NULL)
178 return (q);
179 a = a->q_sibling;
180 }
181 return (NULL);
6eefe4f6
EA
182}
183\f/*
184** RECIPIENT -- Designate a message recipient
185**
186** Saves the named person for future mailing.
187**
188** Parameters:
189** a -- the (preparsed) address header for the recipient.
d4f42161
EA
190** sendq -- a pointer to the head of a queue to put the
191** recipient in. Duplicate supression is done
192** in this queue.
78bbbc48 193** e -- the current envelope.
6eefe4f6
EA
194**
195** Returns:
abae7b2d 196** pointer to address actually inserted in send list.
6eefe4f6
EA
197**
198** Side Effects:
199** none.
200*/
201
0df908a9
KB
202extern ADDRESS *getctladdr();
203
d344c0b7 204ADDRESS *
abae7b2d 205ADDRESS *
a4076aed 206recipient(a, sendq, e)
6eefe4f6 207 register ADDRESS *a;
d4f42161 208 register ADDRESS **sendq;
a4076aed 209 register ENVELOPE *e;
6eefe4f6
EA
210{
211 register ADDRESS *q;
74c5fe7c 212 ADDRESS **pq;
6eefe4f6 213 register struct mailer *m;
98f46225
EA
214 register char *p;
215 bool quoted = FALSE; /* set if the addr has a quote bit */
7f0fd60b 216 int findusercount = 0;
98f46225 217 char buf[MAXNAME]; /* unquoted image of the user name */
118e6693 218 extern int safefile();
6eefe4f6 219
a4076aed 220 e->e_to = a->q_paddr;
179c1218 221 m = a->q_mailer;
6eefe4f6 222 errno = 0;
9678c96d 223 if (tTd(26, 1))
331b7c9f
EA
224 {
225 printf("\nrecipient: ");
226 printaddr(a, FALSE);
227 }
6eefe4f6
EA
228
229 /* break aliasing loops */
230 if (AliasLevel > MAXRCRSN)
231 {
b6edea3d 232 usrerr("554 aliasing/forwarding loop broken");
abae7b2d 233 return (NULL);
6eefe4f6
EA
234 }
235
236 /*
ed45aae1 237 ** Finish setting up address structure.
6eefe4f6
EA
238 */
239
0fe3917f 240 /* set the queue timeout */
ed45aae1
EA
241 a->q_timeout = TimeOut;
242
0fe3917f
EA
243 /* map user & host to lower case if requested on non-aliases */
244 if (a->q_alias == NULL)
245 loweraddr(a);
246
247 /* get unquoted user for file, program or user.name check */
98f46225
EA
248 (void) strcpy(buf, a->q_user);
249 for (p = buf; *p != '\0' && !quoted; p++)
250 {
3eb4fac4 251 if (*p == '\\')
98f46225
EA
252 quoted = TRUE;
253 }
85c61679 254 stripquotes(buf);
98f46225 255
98e5062b 256 /* check for direct mailing to restricted mailers */
78bbbc48 257 if (a->q_alias == NULL && m == ProgMailer)
6eefe4f6 258 {
98e5062b 259 a->q_flags |= QDONTSEND|QBADADDR;
b6edea3d 260 usrerr("550 Cannot mail directly to programs", m->m_name);
6eefe4f6
EA
261 }
262
263 /*
b9ca6d11
EA
264 ** Look up this person in the recipient list.
265 ** If they are there already, return, otherwise continue.
266 ** If the list is empty, just add it. Notice the cute
267 ** hack to make from addresses suppress things correctly:
268 ** the QDONTSEND bit will be set in the send list.
269 ** [Please note: the emphasis is on "hack."]
6eefe4f6
EA
270 */
271
d4f42161 272 for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
6eefe4f6 273 {
35943e55 274 if (sameaddr(q, a))
6eefe4f6 275 {
9678c96d 276 if (tTd(26, 1))
331b7c9f
EA
277 {
278 printf("%s in sendq: ", a->q_paddr);
279 printaddr(q, FALSE);
280 }
92f12b98 281 if (!bitset(QPRIMARY, q->q_flags))
f7eca811
EA
282 {
283 if (!bitset(QDONTSEND, a->q_flags))
b6edea3d 284 message("duplicate suppressed");
92f12b98 285 q->q_flags |= a->q_flags;
f7eca811 286 }
abae7b2d
EA
287 if (!bitset(QPSEUDO, a->q_flags))
288 q->q_flags &= ~QPSEUDO;
289 return (q);
6eefe4f6 290 }
6eefe4f6 291 }
74c5fe7c
EA
292
293 /* add address on list */
294 *pq = a;
6eefe4f6
EA
295 a->q_next = NULL;
296
297 /*
98e5062b 298 ** Alias the name and handle special mailer types.
6eefe4f6
EA
299 */
300
7f0fd60b 301 trylocaluser:
42450b5a
EA
302 if (tTd(29, 7))
303 printf("at trylocaluser %s\n", a->q_user);
304
8bcce465 305 if (bitset(QDONTSEND|QVERIFIED, a->q_flags))
98e5062b
EA
306 return (a);
307
308 if (m == InclMailer)
6eefe4f6 309 {
98e5062b 310 a->q_flags |= QDONTSEND;
78bbbc48 311 if (a->q_alias == NULL)
6eefe4f6 312 {
4aa5a536 313 a->q_flags |= QDONTSEND|QBADADDR;
b6edea3d 314 usrerr("550 Cannot mail directly to :include:s");
6eefe4f6
EA
315 }
316 else
8a12fae4 317 {
118e6693
EA
318 int err;
319
b6edea3d 320 message("including file %s", a->q_user);
118e6693
EA
321 err = include(a->q_user, FALSE, a, sendq, e);
322 if (transienterror(err))
323 a->q_flags |= QQUEUEUP|QDONTSEND;
8a12fae4 324 }
98e5062b 325 }
6e99f903 326 else if (m == FileMailer)
6eefe4f6 327 {
a0554f81
EA
328 struct stat stb;
329 extern bool writable();
6eefe4f6 330
f3d8f6d6 331 p = strrchr(buf, '/');
d13779b1 332 /* check if writable or creatable */
78bbbc48 333 if (a->q_alias == NULL && !QueueRun)
6eefe4f6 334 {
d13779b1 335 a->q_flags |= QDONTSEND|QBADADDR;
b6edea3d 336 usrerr("550 Cannot mail directly to files");
d13779b1
EA
337 }
338 else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) :
118e6693 339 (*p = '\0', safefile(buf, getruid(), S_IWRITE|S_IEXEC) != 0))
d13779b1 340 {
4aa5a536 341 a->q_flags |= QDONTSEND|QBADADDR;
c0ae0b24 342 giveresponse(EX_CANTCREAT, m, NULL, e);
d13779b1 343 }
d13779b1
EA
344 }
345
98e5062b 346 if (m != LocalMailer)
6e99f903
EA
347 {
348 if (!bitset(QDONTSEND, a->q_flags))
349 e->e_nrcpts++;
98e5062b 350 return (a);
6e99f903 351 }
98e5062b
EA
352
353 /* try aliasing */
354 alias(a, sendq, e);
355
356# ifdef USERDB
357 /* if not aliased, look it up in the user database */
358 if (!bitset(QDONTSEND|QNOTREMOTE, a->q_flags))
359 {
360 extern int udbexpand();
361
362 if (udbexpand(a, sendq, e) == EX_TEMPFAIL)
363 {
118e6693 364 a->q_flags |= QQUEUEUP|QDONTSEND;
98e5062b
EA
365 if (e->e_message == NULL)
366 e->e_message = newstr("Deferred: user database error");
367# ifdef LOG
68f7099c 368 if (LogLevel > 8)
98e5062b
EA
369 syslog(LOG_INFO, "%s: deferred: udbexpand",
370 e->e_id);
371# endif
b6edea3d 372 message("queued (user database error)");
6e99f903 373 e->e_nrcpts++;
98e5062b
EA
374 return (a);
375 }
376 }
377# endif
378
379 /* if it was an alias or a UDB expansion, just return now */
118e6693 380 if (bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags))
98e5062b
EA
381 return (a);
382
d13779b1
EA
383 /*
384 ** If we have a level two config file, then pass the name through
385 ** Ruleset 5 before sending it off. Ruleset 5 has the right
386 ** to send rewrite it to another mailer. This gives us a hook
387 ** after local aliasing has been done.
388 */
389
390 if (tTd(29, 5))
391 {
392 printf("recipient: testing local? cl=%d, rr5=%x\n\t",
393 ConfigLevel, RewriteRules[5]);
394 printaddr(a, FALSE);
395 }
396 if (!bitset(QNOTREMOTE, a->q_flags) && ConfigLevel >= 2 &&
397 RewriteRules[5] != NULL)
398 {
a4076aed 399 maplocaluser(a, sendq, e);
d13779b1
EA
400 }
401
402 /*
403 ** If it didn't get rewritten to another mailer, go ahead
404 ** and deliver it.
405 */
406
118e6693 407 if (!bitset(QDONTSEND|QQUEUEUP, a->q_flags))
d13779b1 408 {
42450b5a 409 auto bool fuzzy;
d13779b1
EA
410 register struct passwd *pw;
411 extern struct passwd *finduser();
412
413 /* warning -- finduser may trash buf */
42450b5a 414 pw = finduser(buf, &fuzzy);
d13779b1
EA
415 if (pw == NULL)
416 {
4aa5a536 417 a->q_flags |= QDONTSEND|QBADADDR;
c0ae0b24 418 giveresponse(EX_NOUSER, m, NULL, e);
6eefe4f6
EA
419 }
420 else
421 {
d13779b1 422 char nbuf[MAXNAME];
ff3e3c1c 423
42450b5a 424 if (fuzzy)
6eefe4f6 425 {
7f0fd60b 426 /* name was a fuzzy match */
d13779b1 427 a->q_user = newstr(pw->pw_name);
7f0fd60b
EA
428 if (findusercount++ > 3)
429 {
4aa5a536 430 a->q_flags |= QDONTSEND|QBADADDR;
b6edea3d 431 usrerr("554 aliasing/forwarding loop for %s broken",
7f0fd60b
EA
432 pw->pw_name);
433 return (a);
434 }
435
436 /* see if it aliases */
d13779b1 437 (void) strcpy(buf, pw->pw_name);
7f0fd60b 438 goto trylocaluser;
6eefe4f6 439 }
d13779b1
EA
440 a->q_home = newstr(pw->pw_dir);
441 a->q_uid = pw->pw_uid;
442 a->q_gid = pw->pw_gid;
443 a->q_flags |= QGOODUID;
444 buildfname(pw->pw_gecos, pw->pw_name, nbuf);
445 if (nbuf[0] != '\0')
446 a->q_fullname = newstr(nbuf);
447 if (!quoted)
a4076aed 448 forward(a, sendq, e);
6eefe4f6
EA
449 }
450 }
6e99f903
EA
451 if (!bitset(QDONTSEND, a->q_flags))
452 e->e_nrcpts++;
d344c0b7 453 return (a);
abae7b2d
EA
454
455 return (a);
6eefe4f6
EA
456}
457\f/*
ff3e3c1c
EA
458** FINDUSER -- find the password entry for a user.
459**
460** This looks a lot like getpwnam, except that it may want to
461** do some fancier pattern matching in /etc/passwd.
462**
7338e3d4
EA
463** This routine contains most of the time of many sendmail runs.
464** It deserves to be optimized.
465**
ff3e3c1c
EA
466** Parameters:
467** name -- the name to match against.
42450b5a
EA
468** fuzzyp -- an outarg that is set to TRUE if this entry
469** was found using the fuzzy matching algorithm;
470** set to FALSE otherwise.
ff3e3c1c
EA
471**
472** Returns:
473** A pointer to a pw struct.
474** NULL if name is unknown or ambiguous.
475**
476** Side Effects:
29c33ff6 477** may modify name.
ff3e3c1c
EA
478*/
479
480struct passwd *
42450b5a 481finduser(name, fuzzyp)
ff3e3c1c 482 char *name;
42450b5a 483 bool *fuzzyp;
ff3e3c1c 484{
2b5e3c25 485 register struct passwd *pw;
29c33ff6 486 register char *p;
f74d8dce
EA
487 extern struct passwd *getpwent();
488 extern struct passwd *getpwnam();
29c33ff6 489
42450b5a
EA
490 if (tTd(29, 4))
491 printf("finduser(%s): ", name);
492
639d8b98 493 /* map upper => lower case */
29c33ff6
EA
494 for (p = name; *p != '\0'; p++)
495 {
639d8b98 496 if (isascii(*p) && isupper(*p))
577bce94 497 *p = tolower(*p);
29c33ff6 498 }
42450b5a 499 *fuzzyp = FALSE;
ff3e3c1c 500
639d8b98 501 /* look up this login name using fast path */
77b16ff1 502 if ((pw = getpwnam(name)) != NULL)
42450b5a
EA
503 {
504 if (tTd(29, 4))
505 printf("found (non-fuzzy)\n");
77b16ff1 506 return (pw);
42450b5a 507 }
77b16ff1 508
7f0fd60b
EA
509#ifdef MATCHGECOS
510 /* see if fuzzy matching allowed */
511 if (!MatchGecos)
42450b5a
EA
512 {
513 if (tTd(29, 4))
514 printf("not found (fuzzy disabled)\n");
7f0fd60b 515 return NULL;
42450b5a 516 }
7f0fd60b 517
77b16ff1 518 /* search for a matching full name instead */
639d8b98
EA
519 for (p = name; *p != '\0'; p++)
520 {
521 if (*p == (SpaceSub & 0177) || *p == '_')
522 *p = ' ';
523 }
03388044 524 (void) setpwent();
2b5e3c25
EA
525 while ((pw = getpwent()) != NULL)
526 {
abae7b2d 527 char buf[MAXNAME];
2b5e3c25 528
abae7b2d 529 fullname(pw, buf);
f3d8f6d6 530 if (strchr(buf, ' ') != NULL && !strcasecmp(buf, name))
36292825 531 {
42450b5a
EA
532 if (tTd(29, 4))
533 printf("fuzzy matches %s\n", pw->pw_name);
abae7b2d
EA
534 message(Arpa_Info, "sending to %s <%s>",
535 buf, pw->pw_name);
2b5e3c25 536 return (pw);
36292825 537 }
2b5e3c25 538 }
7f0fd60b 539#endif
42450b5a
EA
540 if (tTd(29, 4))
541 printf("no fuzzy match found\n");
2b5e3c25 542 return (NULL);
ff3e3c1c
EA
543}
544\f/*
a0554f81
EA
545** WRITABLE -- predicate returning if the file is writable.
546**
547** This routine must duplicate the algorithm in sys/fio.c.
548** Unfortunately, we cannot use the access call since we
549** won't necessarily be the real uid when we try to
550** actually open the file.
551**
552** Notice that ANY file with ANY execute bit is automatically
553** not writable. This is also enforced by mailfile.
554**
555** Parameters:
556** s -- pointer to a stat struct for the file.
557**
558** Returns:
559** TRUE -- if we will be able to write this file.
560** FALSE -- if we cannot write this file.
561**
562** Side Effects:
563** none.
564*/
565
566bool
567writable(s)
568 register struct stat *s;
569{
44967af8
EA
570 uid_t euid;
571 gid_t egid;
a0554f81
EA
572 int bits;
573
574 if (bitset(0111, s->st_mode))
575 return (FALSE);
576 euid = getruid();
577 egid = getrgid();
578 if (geteuid() == 0)
579 {
580 if (bitset(S_ISUID, s->st_mode))
581 euid = s->st_uid;
582 if (bitset(S_ISGID, s->st_mode))
583 egid = s->st_gid;
584 }
585
586 if (euid == 0)
587 return (TRUE);
588 bits = S_IWRITE;
589 if (euid != s->st_uid)
590 {
591 bits >>= 3;
592 if (egid != s->st_gid)
593 bits >>= 3;
594 }
595 return ((s->st_mode & bits) != 0);
596}
597\f/*
6eefe4f6
EA
598** INCLUDE -- handle :include: specification.
599**
600** Parameters:
601** fname -- filename to include.
a90a7c55
EA
602** forwarding -- if TRUE, we are reading a .forward file.
603** if FALSE, it's a :include: file.
1bf7c76b
EA
604** ctladdr -- address template to use to fill in these
605** addresses -- effective user/group id are
606** the important things.
d4f42161
EA
607** sendq -- a pointer to the head of the send queue
608** to put these addresses in.
6eefe4f6
EA
609**
610** Returns:
e0136832 611** open error status
6eefe4f6
EA
612**
613** Side Effects:
614** reads the :include: file and sends to everyone
615** listed in that file.
616*/
617
a90a7c55
EA
618static jmp_buf CtxIncludeTimeout;
619
e0136832 620int
a4076aed 621include(fname, forwarding, ctladdr, sendq, e)
6eefe4f6 622 char *fname;
a90a7c55 623 bool forwarding;
1bf7c76b 624 ADDRESS *ctladdr;
d4f42161 625 ADDRESS **sendq;
a4076aed 626 ENVELOPE *e;
6eefe4f6 627{
6eefe4f6 628 register FILE *fp;
a4076aed 629 char *oldto = e->e_to;
7338e3d4
EA
630 char *oldfilename = FileName;
631 int oldlinenumber = LineNumber;
a90a7c55 632 register EVENT *ev = NULL;
1c7897ef 633 int nincludes;
118e6693 634 int ret;
a90a7c55
EA
635 char buf[MAXLINE];
636 static int includetimeout();
637
b21ec539
EA
638 if (tTd(27, 2))
639 printf("include(%s)\n", fname);
640
a90a7c55
EA
641 /*
642 ** If home directory is remote mounted but server is down,
643 ** this can hang or give errors; use a timeout to avoid this
644 */
645
646 if (setjmp(CtxIncludeTimeout) != 0)
647 {
648 ctladdr->q_flags |= QQUEUEUP|QDONTSEND;
649 errno = 0;
650 usrerr("451 open timeout on %s", fname);
e0136832 651 return ETIMEDOUT;
a90a7c55
EA
652 }
653 ev = setevent((time_t) 60, includetimeout, 0);
654
655 /* if forwarding, the input file must be marked safe */
118e6693 656 if (forwarding && (ret = safefile(fname, ctladdr->q_uid, S_IREAD)) != 0)
a90a7c55
EA
657 {
658 /* don't use this .forward file */
659 clrevent(ev);
b21ec539 660 if (tTd(27, 4))
118e6693
EA
661 printf("include: not safe (uid=%d): %s\n",
662 ctladdr->q_uid, errstring(ret));
663 return ret;
a90a7c55 664 }
6eefe4f6 665
6eefe4f6
EA
666 fp = fopen(fname, "r");
667 if (fp == NULL)
668 {
e0136832
EA
669 int ret = errno;
670
5d41b806 671 clrevent(ev);
b6edea3d 672 usrerr("550 Cannot open %s", fname);
e0136832 673 return ret;
6eefe4f6 674 }
a90a7c55 675
962c3fb2
EA
676 if (getctladdr(ctladdr) == NULL)
677 {
678 struct stat st;
679
680 if (fstat(fileno(fp), &st) < 0)
5d41b806
EA
681 {
682 int ret = errno;
683
684 clrevent(ev);
962c3fb2 685 syserr("Cannot fstat %s!", fname);
5d41b806
EA
686 return ret;
687 }
962c3fb2
EA
688 ctladdr->q_uid = st.st_uid;
689 ctladdr->q_gid = st.st_gid;
690 ctladdr->q_flags |= QGOODUID;
691 }
6eefe4f6 692
a90a7c55
EA
693 clrevent(ev);
694
8f48def8
EA
695 if (bitset(EF_VRFYONLY, e->e_flags))
696 {
697 /* don't do any more now */
698 fclose(fp);
699 return 0;
700 }
701
6eefe4f6 702 /* read the file -- each line is a comma-separated list. */
7338e3d4
EA
703 FileName = fname;
704 LineNumber = 0;
1c7897ef
EA
705 ctladdr->q_flags &= ~QSELFREF;
706 nincludes = 0;
6eefe4f6
EA
707 while (fgets(buf, sizeof buf, fp) != NULL)
708 {
f3d8f6d6 709 register char *p = strchr(buf, '\n');
6eefe4f6 710
dd0758e5 711 LineNumber++;
6eefe4f6
EA
712 if (p != NULL)
713 *p = '\0';
b21ec539 714 if (buf[0] == '#' || buf[0] == '\0')
af04f6e4 715 continue;
51d9cc47 716 e->e_to = NULL;
b6edea3d 717 message("%s to %s",
a90a7c55 718 forwarding ? "forwarding" : "sending", buf);
aa102c71 719#ifdef LOG
68f7099c 720 if (forwarding && LogLevel > 9)
aa102c71
EA
721 syslog(LOG_INFO, "%s: forward %s => %s",
722 e->e_id, oldto, buf);
723#endif
724
23008226 725 AliasLevel++;
abae7b2d 726 sendto(buf, 1, ctladdr, 0);
23008226 727 AliasLevel--;
6eefe4f6 728 }
1c7897ef 729 if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags))
f7eca811
EA
730 {
731 if (tTd(27, 5))
732 {
733 printf("include: QDONTSEND ");
734 printaddr(ctladdr, FALSE);
735 }
736 ctladdr->q_flags |= QDONTSEND;
737 }
6eefe4f6 738
74c5fe7c 739 (void) fclose(fp);
7338e3d4
EA
740 FileName = oldfilename;
741 LineNumber = oldlinenumber;
e0136832 742 return 0;
6eefe4f6 743}
a90a7c55
EA
744
745static
746includetimeout()
747{
748 longjmp(CtxIncludeTimeout, 1);
749}
d6b27179
EA
750\f/*
751** SENDTOARGV -- send to an argument vector.
752**
753** Parameters:
754** argv -- argument vector to send to.
118e6693 755** e -- the current envelope.
d6b27179
EA
756**
757** Returns:
758** none.
759**
760** Side Effects:
761** puts all addresses on the argument vector onto the
762** send queue.
763*/
764
a4076aed 765sendtoargv(argv, e)
d6b27179 766 register char **argv;
a4076aed 767 register ENVELOPE *e;
d6b27179
EA
768{
769 register char *p;
d6b27179
EA
770
771 while ((p = *argv++) != NULL)
772 {
ed73ef1d 773 if (argv[0] != NULL && argv[1] != NULL && !strcasecmp(argv[0], "at"))
d6b27179
EA
774 {
775 char nbuf[MAXNAME];
776
777 if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf)
b6edea3d 778 usrerr("554 address overflow");
d6b27179
EA
779 else
780 {
781 (void) strcpy(nbuf, p);
782 (void) strcat(nbuf, "@");
783 (void) strcat(nbuf, argv[1]);
784 p = newstr(nbuf);
785 argv += 2;
786 }
787 }
abae7b2d 788 sendto(p, 0, (ADDRESS *) NULL, 0);
d6b27179
EA
789 }
790}
1bf7c76b
EA
791\f/*
792** GETCTLADDR -- get controlling address from an address header.
793**
794** If none, get one corresponding to the effective userid.
795**
796** Parameters:
797** a -- the address to find the controller of.
798**
799** Returns:
800** the controlling address.
801**
802** Side Effects:
803** none.
804*/
805
806ADDRESS *
807getctladdr(a)
808 register ADDRESS *a;
809{
2c1457f0 810 while (a != NULL && !bitset(QGOODUID, a->q_flags))
1bf7c76b 811 a = a->q_alias;
1bf7c76b
EA
812 return (a);
813}