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