typo
[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
c0ae0b24 10static char sccsid[] = "@(#)recipient.c 6.22 (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 {
98e5062b 313 a->q_flags |= 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
EA
340 {
341 a->q_flags |= 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 {
417 a->q_flags |= 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 {
b6edea3d 430 usrerr("554 aliasing/forwarding loop for %s broken",
7f0fd60b
EA
431 pw->pw_name);
432 return (a);
433 }
434
435 /* see if it aliases */
d13779b1 436 (void) strcpy(buf, pw->pw_name);
7f0fd60b 437 goto trylocaluser;
6eefe4f6 438 }
d13779b1
EA
439 a->q_home = newstr(pw->pw_dir);
440 a->q_uid = pw->pw_uid;
441 a->q_gid = pw->pw_gid;
442 a->q_flags |= QGOODUID;
443 buildfname(pw->pw_gecos, pw->pw_name, nbuf);
444 if (nbuf[0] != '\0')
445 a->q_fullname = newstr(nbuf);
446 if (!quoted)
a4076aed 447 forward(a, sendq, e);
6eefe4f6
EA
448 }
449 }
6e99f903
EA
450 if (!bitset(QDONTSEND, a->q_flags))
451 e->e_nrcpts++;
d344c0b7 452 return (a);
abae7b2d
EA
453
454 return (a);
6eefe4f6
EA
455}
456\f/*
ff3e3c1c
EA
457** FINDUSER -- find the password entry for a user.
458**
459** This looks a lot like getpwnam, except that it may want to
460** do some fancier pattern matching in /etc/passwd.
461**
7338e3d4
EA
462** This routine contains most of the time of many sendmail runs.
463** It deserves to be optimized.
464**
ff3e3c1c
EA
465** Parameters:
466** name -- the name to match against.
42450b5a
EA
467** fuzzyp -- an outarg that is set to TRUE if this entry
468** was found using the fuzzy matching algorithm;
469** set to FALSE otherwise.
ff3e3c1c
EA
470**
471** Returns:
472** A pointer to a pw struct.
473** NULL if name is unknown or ambiguous.
474**
475** Side Effects:
29c33ff6 476** may modify name.
ff3e3c1c
EA
477*/
478
479struct passwd *
42450b5a 480finduser(name, fuzzyp)
ff3e3c1c 481 char *name;
42450b5a 482 bool *fuzzyp;
ff3e3c1c 483{
2b5e3c25 484 register struct passwd *pw;
29c33ff6 485 register char *p;
f74d8dce
EA
486 extern struct passwd *getpwent();
487 extern struct passwd *getpwnam();
29c33ff6 488
42450b5a
EA
489 if (tTd(29, 4))
490 printf("finduser(%s): ", name);
491
639d8b98 492 /* map upper => lower case */
29c33ff6
EA
493 for (p = name; *p != '\0'; p++)
494 {
639d8b98 495 if (isascii(*p) && isupper(*p))
577bce94 496 *p = tolower(*p);
29c33ff6 497 }
42450b5a 498 *fuzzyp = FALSE;
ff3e3c1c 499
639d8b98 500 /* look up this login name using fast path */
77b16ff1 501 if ((pw = getpwnam(name)) != NULL)
42450b5a
EA
502 {
503 if (tTd(29, 4))
504 printf("found (non-fuzzy)\n");
77b16ff1 505 return (pw);
42450b5a 506 }
77b16ff1 507
7f0fd60b
EA
508#ifdef MATCHGECOS
509 /* see if fuzzy matching allowed */
510 if (!MatchGecos)
42450b5a
EA
511 {
512 if (tTd(29, 4))
513 printf("not found (fuzzy disabled)\n");
7f0fd60b 514 return NULL;
42450b5a 515 }
7f0fd60b 516
77b16ff1 517 /* search for a matching full name instead */
639d8b98
EA
518 for (p = name; *p != '\0'; p++)
519 {
520 if (*p == (SpaceSub & 0177) || *p == '_')
521 *p = ' ';
522 }
03388044 523 (void) setpwent();
2b5e3c25
EA
524 while ((pw = getpwent()) != NULL)
525 {
abae7b2d 526 char buf[MAXNAME];
2b5e3c25 527
abae7b2d 528 fullname(pw, buf);
f3d8f6d6 529 if (strchr(buf, ' ') != NULL && !strcasecmp(buf, name))
36292825 530 {
42450b5a
EA
531 if (tTd(29, 4))
532 printf("fuzzy matches %s\n", pw->pw_name);
abae7b2d
EA
533 message(Arpa_Info, "sending to %s <%s>",
534 buf, pw->pw_name);
2b5e3c25 535 return (pw);
36292825 536 }
2b5e3c25 537 }
7f0fd60b 538#endif
42450b5a
EA
539 if (tTd(29, 4))
540 printf("no fuzzy match found\n");
2b5e3c25 541 return (NULL);
ff3e3c1c
EA
542}
543\f/*
a0554f81
EA
544** WRITABLE -- predicate returning if the file is writable.
545**
546** This routine must duplicate the algorithm in sys/fio.c.
547** Unfortunately, we cannot use the access call since we
548** won't necessarily be the real uid when we try to
549** actually open the file.
550**
551** Notice that ANY file with ANY execute bit is automatically
552** not writable. This is also enforced by mailfile.
553**
554** Parameters:
555** s -- pointer to a stat struct for the file.
556**
557** Returns:
558** TRUE -- if we will be able to write this file.
559** FALSE -- if we cannot write this file.
560**
561** Side Effects:
562** none.
563*/
564
565bool
566writable(s)
567 register struct stat *s;
568{
44967af8
EA
569 uid_t euid;
570 gid_t egid;
a0554f81
EA
571 int bits;
572
573 if (bitset(0111, s->st_mode))
574 return (FALSE);
575 euid = getruid();
576 egid = getrgid();
577 if (geteuid() == 0)
578 {
579 if (bitset(S_ISUID, s->st_mode))
580 euid = s->st_uid;
581 if (bitset(S_ISGID, s->st_mode))
582 egid = s->st_gid;
583 }
584
585 if (euid == 0)
586 return (TRUE);
587 bits = S_IWRITE;
588 if (euid != s->st_uid)
589 {
590 bits >>= 3;
591 if (egid != s->st_gid)
592 bits >>= 3;
593 }
594 return ((s->st_mode & bits) != 0);
595}
596\f/*
6eefe4f6
EA
597** INCLUDE -- handle :include: specification.
598**
599** Parameters:
600** fname -- filename to include.
a90a7c55
EA
601** forwarding -- if TRUE, we are reading a .forward file.
602** if FALSE, it's a :include: file.
1bf7c76b
EA
603** ctladdr -- address template to use to fill in these
604** addresses -- effective user/group id are
605** the important things.
d4f42161
EA
606** sendq -- a pointer to the head of the send queue
607** to put these addresses in.
6eefe4f6
EA
608**
609** Returns:
e0136832 610** open error status
6eefe4f6
EA
611**
612** Side Effects:
613** reads the :include: file and sends to everyone
614** listed in that file.
615*/
616
a90a7c55
EA
617static jmp_buf CtxIncludeTimeout;
618
e0136832 619int
a4076aed 620include(fname, forwarding, ctladdr, sendq, e)
6eefe4f6 621 char *fname;
a90a7c55 622 bool forwarding;
1bf7c76b 623 ADDRESS *ctladdr;
d4f42161 624 ADDRESS **sendq;
a4076aed 625 ENVELOPE *e;
6eefe4f6 626{
6eefe4f6 627 register FILE *fp;
a4076aed 628 char *oldto = e->e_to;
7338e3d4
EA
629 char *oldfilename = FileName;
630 int oldlinenumber = LineNumber;
a90a7c55 631 register EVENT *ev = NULL;
1c7897ef 632 int nincludes;
118e6693 633 int ret;
a90a7c55
EA
634 char buf[MAXLINE];
635 static int includetimeout();
636
b21ec539
EA
637 if (tTd(27, 2))
638 printf("include(%s)\n", fname);
639
a90a7c55
EA
640 /*
641 ** If home directory is remote mounted but server is down,
642 ** this can hang or give errors; use a timeout to avoid this
643 */
644
645 if (setjmp(CtxIncludeTimeout) != 0)
646 {
647 ctladdr->q_flags |= QQUEUEUP|QDONTSEND;
648 errno = 0;
649 usrerr("451 open timeout on %s", fname);
e0136832 650 return ETIMEDOUT;
a90a7c55
EA
651 }
652 ev = setevent((time_t) 60, includetimeout, 0);
653
654 /* if forwarding, the input file must be marked safe */
118e6693 655 if (forwarding && (ret = safefile(fname, ctladdr->q_uid, S_IREAD)) != 0)
a90a7c55
EA
656 {
657 /* don't use this .forward file */
658 clrevent(ev);
b21ec539 659 if (tTd(27, 4))
118e6693
EA
660 printf("include: not safe (uid=%d): %s\n",
661 ctladdr->q_uid, errstring(ret));
662 return ret;
a90a7c55 663 }
6eefe4f6 664
6eefe4f6
EA
665 fp = fopen(fname, "r");
666 if (fp == NULL)
667 {
e0136832
EA
668 int ret = errno;
669
5d41b806 670 clrevent(ev);
b6edea3d 671 usrerr("550 Cannot open %s", fname);
e0136832 672 return ret;
6eefe4f6 673 }
a90a7c55 674
962c3fb2
EA
675 if (getctladdr(ctladdr) == NULL)
676 {
677 struct stat st;
678
679 if (fstat(fileno(fp), &st) < 0)
5d41b806
EA
680 {
681 int ret = errno;
682
683 clrevent(ev);
962c3fb2 684 syserr("Cannot fstat %s!", fname);
5d41b806
EA
685 return ret;
686 }
962c3fb2
EA
687 ctladdr->q_uid = st.st_uid;
688 ctladdr->q_gid = st.st_gid;
689 ctladdr->q_flags |= QGOODUID;
690 }
6eefe4f6 691
a90a7c55
EA
692 clrevent(ev);
693
8f48def8
EA
694 if (bitset(EF_VRFYONLY, e->e_flags))
695 {
696 /* don't do any more now */
697 fclose(fp);
698 return 0;
699 }
700
6eefe4f6 701 /* read the file -- each line is a comma-separated list. */
7338e3d4
EA
702 FileName = fname;
703 LineNumber = 0;
1c7897ef
EA
704 ctladdr->q_flags &= ~QSELFREF;
705 nincludes = 0;
6eefe4f6
EA
706 while (fgets(buf, sizeof buf, fp) != NULL)
707 {
f3d8f6d6 708 register char *p = strchr(buf, '\n');
6eefe4f6 709
dd0758e5 710 LineNumber++;
6eefe4f6
EA
711 if (p != NULL)
712 *p = '\0';
b21ec539 713 if (buf[0] == '#' || buf[0] == '\0')
af04f6e4 714 continue;
51d9cc47 715 e->e_to = NULL;
b6edea3d 716 message("%s to %s",
a90a7c55 717 forwarding ? "forwarding" : "sending", buf);
aa102c71 718#ifdef LOG
68f7099c 719 if (forwarding && LogLevel > 9)
aa102c71
EA
720 syslog(LOG_INFO, "%s: forward %s => %s",
721 e->e_id, oldto, buf);
722#endif
723
23008226 724 AliasLevel++;
abae7b2d 725 sendto(buf, 1, ctladdr, 0);
23008226 726 AliasLevel--;
6eefe4f6 727 }
1c7897ef 728 if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags))
f7eca811
EA
729 {
730 if (tTd(27, 5))
731 {
732 printf("include: QDONTSEND ");
733 printaddr(ctladdr, FALSE);
734 }
735 ctladdr->q_flags |= QDONTSEND;
736 }
6eefe4f6 737
74c5fe7c 738 (void) fclose(fp);
7338e3d4
EA
739 FileName = oldfilename;
740 LineNumber = oldlinenumber;
e0136832 741 return 0;
6eefe4f6 742}
a90a7c55
EA
743
744static
745includetimeout()
746{
747 longjmp(CtxIncludeTimeout, 1);
748}
d6b27179
EA
749\f/*
750** SENDTOARGV -- send to an argument vector.
751**
752** Parameters:
753** argv -- argument vector to send to.
118e6693 754** e -- the current envelope.
d6b27179
EA
755**
756** Returns:
757** none.
758**
759** Side Effects:
760** puts all addresses on the argument vector onto the
761** send queue.
762*/
763
a4076aed 764sendtoargv(argv, e)
d6b27179 765 register char **argv;
a4076aed 766 register ENVELOPE *e;
d6b27179
EA
767{
768 register char *p;
d6b27179
EA
769
770 while ((p = *argv++) != NULL)
771 {
ed73ef1d 772 if (argv[0] != NULL && argv[1] != NULL && !strcasecmp(argv[0], "at"))
d6b27179
EA
773 {
774 char nbuf[MAXNAME];
775
776 if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf)
b6edea3d 777 usrerr("554 address overflow");
d6b27179
EA
778 else
779 {
780 (void) strcpy(nbuf, p);
781 (void) strcat(nbuf, "@");
782 (void) strcat(nbuf, argv[1]);
783 p = newstr(nbuf);
784 argv += 2;
785 }
786 }
abae7b2d 787 sendto(p, 0, (ADDRESS *) NULL, 0);
d6b27179
EA
788 }
789}
1bf7c76b
EA
790\f/*
791** GETCTLADDR -- get controlling address from an address header.
792**
793** If none, get one corresponding to the effective userid.
794**
795** Parameters:
796** a -- the address to find the controller of.
797**
798** Returns:
799** the controlling address.
800**
801** Side Effects:
802** none.
803*/
804
805ADDRESS *
806getctladdr(a)
807 register ADDRESS *a;
808{
2c1457f0 809 while (a != NULL && !bitset(QGOODUID, a->q_flags))
1bf7c76b 810 a = a->q_alias;
1bf7c76b
EA
811 return (a);
812}