avoid MIMEing RFC1049 messages
[unix-history] / usr / src / usr.sbin / sendmail / src / headers.c
CommitLineData
b2a81223 1/*
792e6158 2 * Copyright (c) 1983, 1995 Eric P. Allman
eb0bafab
KB
3 * Copyright (c) 1988, 1993
4 * The Regents of the University of California. All rights reserved.
bee79b64 5 *
417f7a11 6 * %sccs.include.redist.c%
bee79b64 7 */
b2a81223
DF
8
9#ifndef lint
a5386d1b 10static char sccsid[] = "@(#)headers.c 8.69 (Berkeley) %G%";
bee79b64 11#endif /* not lint */
b2a81223 12
f06af564
EA
13# include <errno.h>
14# include "sendmail.h"
15
f06af564
EA
16/*
17** CHOMPHEADER -- process and save a header line.
18**
19** Called by collect and by readcf to deal with header lines.
20**
21** Parameters:
22** line -- header as a text line.
23** def -- if set, this is a default value.
9905202c 24** hdrp -- a pointer to the place to save the header.
a4076aed 25** e -- the envelope including this header.
f06af564
EA
26**
27** Returns:
28** flags for this header.
29**
30** Side Effects:
31** The header is saved on the header list.
74c5fe7c 32** Contents of 'line' are destroyed.
f06af564
EA
33*/
34
179d940c 35int
9905202c 36chompheader(line, def, hdrp, e)
f06af564
EA
37 char *line;
38 bool def;
9905202c 39 HDR **hdrp;
a4076aed 40 register ENVELOPE *e;
f06af564
EA
41{
42 register char *p;
43 register HDR *h;
44 HDR **hp;
f06af564
EA
45 char *fname;
46 char *fvalue;
47 struct hdrinfo *hi;
be2fcca9 48 bool cond = FALSE;
9905202c 49 bool headeronly;
1dbda134 50 BITMAP mopts;
8446c922 51 char buf[MAXNAME + 1];
abae7b2d 52 extern ADDRESS *sendto();
f06af564 53
9678c96d 54 if (tTd(31, 6))
a44b7a41
EA
55 {
56 printf("chompheader: ");
57 xputs(line);
58 printf("\n");
59 }
9678c96d 60
9905202c
EA
61 headeronly = hdrp != NULL;
62 if (!headeronly)
63 hdrp = &e->e_header;
64
ed45aae1 65 /* strip off options */
1dbda134 66 clrbitmap(mopts);
ed45aae1 67 p = line;
b46fb70f 68 if (*p == '?')
ed45aae1
EA
69 {
70 /* have some */
f3d8f6d6 71 register char *q = strchr(p + 1, *p);
ed45aae1
EA
72
73 if (q != NULL)
74 {
75 *q++ = '\0';
1dbda134
EA
76 while (*++p != '\0')
77 setbitn(*p, mopts);
ed45aae1
EA
78 p = q;
79 }
80 else
277e9e5e 81 syserr("553 header syntax error, line \"%s\"", line);
be2fcca9 82 cond = TRUE;
ed45aae1
EA
83 }
84
f06af564 85 /* find canonical name */
ed45aae1 86 fname = p;
64c7c6da
EA
87 while (isascii(*p) && isgraph(*p) && *p != ':')
88 p++;
89 fvalue = p;
90 while (isascii(*p) && isspace(*p))
91 p++;
db33fce2 92 if (*p++ != ':' || fname == fvalue)
e90f41e7 93 {
b6edea3d 94 syserr("553 header syntax error, line \"%s\"", line);
e90f41e7
EA
95 return (0);
96 }
64c7c6da
EA
97 *fvalue = '\0';
98 fvalue = p;
f06af564
EA
99
100 /* strip field value on front */
101 if (*fvalue == ' ')
102 fvalue++;
103
f06af564
EA
104 /* see if it is a known type */
105 for (hi = HdrInfo; hi->hi_field != NULL; hi++)
106 {
b6919a63 107 if (strcasecmp(hi->hi_field, fname) == 0)
f06af564
EA
108 break;
109 }
110
c93a732e
EA
111 if (tTd(31, 9))
112 {
113 if (hi->hi_field == NULL)
114 printf("no header match\n");
115 else
07e8718d 116 printf("header match, hi_flags=%x\n", hi->hi_flags);
c93a732e
EA
117 }
118
a90807d8 119 /* see if this is a resent message */
9905202c 120 if (!def && !headeronly && bitset(H_RESENT, hi->hi_flags))
a4076aed 121 e->e_flags |= EF_RESENT;
a90807d8 122
b7b719e4 123 /* if this is an Errors-To: header keep track of it now */
9905202c
EA
124 if (UseErrorsTo && !def && !headeronly &&
125 bitset(H_ERRORSTO, hi->hi_flags))
b7b719e4
EA
126 (void) sendtolist(fvalue, NULLADDR, &e->e_errorqueue, 0, e);
127
f06af564
EA
128 /* if this means "end of header" quit now */
129 if (bitset(H_EOH, hi->hi_flags))
130 return (hi->hi_flags);
131
9791b2da
EA
132 /*
133 ** Drop explicit From: if same as what we would generate.
134 ** This is to make MH (which doesn't always give a full name)
135 ** insert the full name information in all circumstances.
136 */
137
03963ff1 138 p = "resent-from";
a4076aed 139 if (!bitset(EF_RESENT, e->e_flags))
03963ff1 140 p += 7;
9905202c
EA
141 if (!def && !headeronly && !bitset(EF_QUEUERUN, e->e_flags) &&
142 strcasecmp(fname, p) == 0)
a90807d8 143 {
8e5c6745
EA
144 if (tTd(31, 2))
145 {
146 printf("comparing header from (%s) against default (%s or %s)\n",
147 fvalue, e->e_from.q_paddr, e->e_from.q_user);
148 }
a4076aed 149 if (e->e_from.q_paddr != NULL &&
8e5c6745
EA
150 (strcmp(fvalue, e->e_from.q_paddr) == 0 ||
151 strcmp(fvalue, e->e_from.q_user) == 0))
a90807d8 152 return (hi->hi_flags);
c6094a3f 153#ifdef MAYBENEXTRELEASE /* XXX UNTESTED XXX UNTESTED XXX UNTESTED XXX */
0159023b 154#if USERDB
c6094a3f
EA
155 else
156 {
157 auto ADDRESS a;
158 char *fancy;
05c33454 159 bool oldSuprErrs = SuprErrs;
c6094a3f
EA
160 extern char *crackaddr();
161 extern char *udbsender();
162
9791b2da
EA
163 /*
164 ** Try doing USERDB rewriting even on fully commented
165 ** names; this saves the "comment" information (such
166 ** as full name) and rewrites the electronic part.
0c35528d
EA
167 **
168 ** XXX This code doesn't belong here -- parsing should
169 ** XXX not be done during collect() phase because
170 ** XXX error messages can confuse the SMTP phase.
05c33454 171 ** XXX Setting SuprErrs is a crude hack around this
0c35528d 172 ** XXX problem.
9791b2da
EA
173 */
174
0c35528d 175 if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
05c33454 176 SuprErrs = TRUE;
c6094a3f
EA
177 fancy = crackaddr(fvalue);
178 if (parseaddr(fvalue, &a, RF_COPYNONE, '\0', NULL, e) != NULL &&
2bade550 179 bitnset(M_CHECKUDB, a.q_mailer->m_flags) &&
c6094a3f
EA
180 (p = udbsender(a.q_user)) != NULL)
181 {
182 char *oldg = macvalue('g', e);
183
184 define('g', p, e);
832e8a27 185 expand(fancy, buf, sizeof buf, e);
c6094a3f
EA
186 define('g', oldg, e);
187 fvalue = buf;
188 }
05c33454 189 SuprErrs = oldSuprErrs;
c6094a3f
EA
190 }
191#endif
192#endif
03963ff1
EA
193 }
194
f68d0afc
EA
195 /* drop forged Sender: values */
196 p = "resent-sender";
197 if (!bitset(EF_RESENT, CurEnv->e_flags))
198 p += 7;
199 if (!def && !QueueRun && CurEnv->e_from.q_mailer == LocalMailer &&
200 bitset(H_VALID, hi->hi_flags))
201 {
202 return (hi->hi_flags);
203 }
204
03963ff1 205 /* delete default value for this header */
9905202c 206 for (hp = hdrp; (h = *hp) != NULL; hp = &h->h_link)
03963ff1 207 {
b6919a63 208 if (strcasecmp(fname, h->h_field) == 0 &&
03963ff1
EA
209 bitset(H_DEFAULT, h->h_flags) &&
210 !bitset(H_FORCE, h->h_flags))
e7ebf20a 211 {
03963ff1 212 h->h_value = NULL;
e7ebf20a
EA
213 if (!cond)
214 {
215 /* copy conditions from default case */
216 bcopy((char *)h->h_mflags, (char *)mopts,
217 sizeof mopts);
218 }
219 }
a90807d8
EA
220 }
221
7f668477
EA
222 /* create a new node */
223 h = (HDR *) xalloc(sizeof *h);
224 h->h_field = newstr(fname);
cd3e07da 225 h->h_value = newstr(fvalue);
7f668477 226 h->h_link = NULL;
17a67c62 227 bcopy((char *) mopts, (char *) h->h_mflags, sizeof mopts);
7f668477 228 *hp = h;
fb35a67c 229 h->h_flags = hi->hi_flags;
f06af564
EA
230 if (def)
231 h->h_flags |= H_DEFAULT;
be2fcca9
EA
232 if (cond)
233 h->h_flags |= H_CHECK;
abae7b2d 234 (void) sendto(h->h_value, 0, (ADDRESS *) NULL, 0);
f06af564 235
3df53d78 236 /* hack to see if this is a new format message */
9905202c 237 if (!def && !headeronly && bitset(H_RCPT|H_FROM, h->h_flags) &&
f3d8f6d6
EA
238 (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL ||
239 strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL))
9ed29988 240 {
a4076aed 241 e->e_flags &= ~EF_OLDSTYLE;
9ed29988 242 }
3df53d78 243
f06af564
EA
244 return (h->h_flags);
245}
246\f/*
dd1fe05b
EA
247** ADDHEADER -- add a header entry to the end of the queue.
248**
249** This bypasses the special checking of chompheader.
250**
251** Parameters:
b6919a63 252** field -- the name of the header field.
94bc039a 253** value -- the value of the field.
c23930c0 254** hp -- an indirect pointer to the header structure list.
dd1fe05b
EA
255**
256** Returns:
257** none.
258**
259** Side Effects:
260** adds the field on the list of headers for this envelope.
261*/
262
179d940c 263void
c23930c0 264addheader(field, value, hdrlist)
dd1fe05b
EA
265 char *field;
266 char *value;
c23930c0 267 HDR **hdrlist;
dd1fe05b
EA
268{
269 register HDR *h;
270 register struct hdrinfo *hi;
271 HDR **hp;
272
273 /* find info struct */
274 for (hi = HdrInfo; hi->hi_field != NULL; hi++)
275 {
b6919a63 276 if (strcasecmp(field, hi->hi_field) == 0)
dd1fe05b
EA
277 break;
278 }
279
280 /* find current place in list -- keep back pointer? */
c23930c0 281 for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link)
dd1fe05b 282 {
b6919a63 283 if (strcasecmp(field, h->h_field) == 0)
dd1fe05b
EA
284 break;
285 }
286
287 /* allocate space for new header */
288 h = (HDR *) xalloc(sizeof *h);
289 h->h_field = field;
290 h->h_value = newstr(value);
f0375650 291 h->h_link = *hp;
dd1fe05b 292 h->h_flags = hi->hi_flags | H_DEFAULT;
1dbda134 293 clrbitmap(h->h_mflags);
dd1fe05b
EA
294 *hp = h;
295}
296\f/*
f06af564
EA
297** HVALUE -- return value of a header.
298**
299** Only "real" fields (i.e., ones that have not been supplied
300** as a default) are used.
301**
302** Parameters:
303** field -- the field name.
c23930c0 304** header -- the header list.
f06af564
EA
305**
306** Returns:
307** pointer to the value part.
308** NULL if not found.
309**
310** Side Effects:
7338e3d4 311** none.
f06af564
EA
312*/
313
314char *
c23930c0 315hvalue(field, header)
f06af564 316 char *field;
c23930c0 317 HDR *header;
f06af564
EA
318{
319 register HDR *h;
320
c23930c0 321 for (h = header; h != NULL; h = h->h_link)
f06af564 322 {
b6919a63
EA
323 if (!bitset(H_DEFAULT, h->h_flags) &&
324 strcasecmp(h->h_field, field) == 0)
f06af564 325 return (h->h_value);
f06af564
EA
326 }
327 return (NULL);
328}
329\f/*
330** ISHEADER -- predicate telling if argument is a header.
331**
74c5fe7c
EA
332** A line is a header if it has a single word followed by
333** optional white space followed by a colon.
334**
9905202c
EA
335** Header fields beginning with two dashes, although technically
336** permitted by RFC822, are automatically rejected in order
337** to make MIME work out. Without this we could have a technically
338** legal header such as ``--"foo:bar"'' that would also be a legal
339** MIME separator.
340**
f06af564 341** Parameters:
277e9e5e 342** h -- string to check for possible headerness.
f06af564
EA
343**
344** Returns:
277e9e5e 345** TRUE if h is a header.
f06af564
EA
346** FALSE otherwise.
347**
348** Side Effects:
349** none.
350*/
351
352bool
277e9e5e
EA
353isheader(h)
354 char *h;
f06af564 355{
277e9e5e
EA
356 register char *s = h;
357
9905202c
EA
358 if (s[0] == '-' && s[1] == '-')
359 return FALSE;
360
7338e3d4 361 while (*s > ' ' && *s != ':' && *s != '\0')
f06af564 362 s++;
7338e3d4 363
277e9e5e
EA
364 if (h == s)
365 return FALSE;
366
7338e3d4 367 /* following technically violates RFC822 */
2bee003d 368 while (isascii(*s) && isspace(*s))
f06af564 369 s++;
7338e3d4 370
f06af564
EA
371 return (*s == ':');
372}
028b97f3 373\f/*
75a2bcaf
EA
374** EATHEADER -- run through the stored header and extract info.
375**
376** Parameters:
7338e3d4 377** e -- the envelope to process.
959cf51d 378** full -- if set, do full processing (e.g., compute
5a6f454c
EA
379** message priority). This should not be set
380** when reading a queue file because some info
381** needed to compute the priority is wrong.
75a2bcaf
EA
382**
383** Returns:
384** none.
385**
386** Side Effects:
387** Sets a bunch of global variables from information
7338e3d4
EA
388** in the collected header.
389** Aborts the message if the hop count is exceeded.
75a2bcaf
EA
390*/
391
179d940c 392void
959cf51d 393eatheader(e, full)
7338e3d4 394 register ENVELOPE *e;
959cf51d 395 bool full;
75a2bcaf
EA
396{
397 register HDR *h;
398 register char *p;
7338e3d4 399 int hopcnt = 0;
33844dcf 400 char *msgid;
3a848ece
EA
401 char buf[MAXLINE];
402
403 /*
404 ** Set up macros for possible expansion in headers.
405 */
406
4a2da288
EA
407 define('f', e->e_sender, e);
408 define('g', e->e_sender, e);
d4f5b98a
EA
409 if (e->e_origrcpt != NULL && *e->e_origrcpt != '\0')
410 define('u', e->e_origrcpt, e);
411 else
412 define('u', NULL, e);
75a2bcaf 413
908e1c74 414 /* full name of from person */
c23930c0 415 p = hvalue("full-name", e->e_header);
908e1c74
EA
416 if (p != NULL)
417 define('x', p, e);
418
7338e3d4
EA
419 if (tTd(32, 1))
420 printf("----- collected header -----\n");
5a6f454c 421 msgid = NULL;
7338e3d4 422 for (h = e->e_header; h != NULL; h = h->h_link)
75a2bcaf 423 {
6d8bbe53
EA
424 if (tTd(32, 1))
425 printf("%s: ", h->h_field);
3b06f2bd
EA
426 if (h->h_value == NULL)
427 {
428 if (tTd(32, 1))
6d8bbe53 429 printf("<NULL>\n");
3b06f2bd
EA
430 continue;
431 }
432
3a848ece 433 /* do early binding */
3b06f2bd 434 if (bitset(H_DEFAULT, h->h_flags))
3a848ece 435 {
6d8bbe53
EA
436 if (tTd(32, 1))
437 {
438 printf("(");
439 xputs(h->h_value);
440 printf(") ");
441 }
832e8a27 442 expand(h->h_value, buf, sizeof buf, e);
3a848ece
EA
443 if (buf[0] != '\0')
444 {
3a848ece
EA
445 h->h_value = newstr(buf);
446 h->h_flags &= ~H_DEFAULT;
447 }
448 }
449
7338e3d4 450 if (tTd(32, 1))
da9633d1 451 {
da9633d1
EA
452 xputs(h->h_value);
453 printf("\n");
454 }
453139c0 455
a90807d8 456 /* count the number of times it has been processed */
7338e3d4
EA
457 if (bitset(H_TRACE, h->h_flags))
458 hopcnt++;
a90807d8
EA
459
460 /* send to this person if we so desire */
461 if (GrabTo && bitset(H_RCPT, h->h_flags) &&
462 !bitset(H_DEFAULT, h->h_flags) &&
a4076aed 463 (!bitset(EF_RESENT, e->e_flags) || bitset(H_RESENT, h->h_flags)))
a90807d8 464 {
d4f6a25e
EA
465 int saveflags = e->e_flags;
466
c93a732e 467 (void) sendtolist(h->h_value, NULLADDR,
f8c2f9fd 468 &e->e_sendqueue, 0, e);
d4f6a25e
EA
469
470 /* delete fatal errors generated by this address */
d4f5b98a 471 if (!GrabTo && !bitset(EF_FATALERRS, saveflags))
d4f6a25e 472 e->e_flags &= ~EF_FATALERRS;
a90807d8
EA
473 }
474
33844dcf 475 /* save the message-id for logging */
5a6f454c 476 if (strcasecmp(h->h_field, "message-id") == 0)
4e8842eb 477 {
33844dcf 478 msgid = h->h_value;
9f0b3b43
EA
479 while (isascii(*msgid) && isspace(*msgid))
480 msgid++;
4e8842eb 481 }
453139c0
EA
482
483 /* see if this is a return-receipt header */
484 if (bitset(H_RECEIPTTO, h->h_flags))
485 e->e_receiptto = h->h_value;
75a2bcaf 486 }
7338e3d4
EA
487 if (tTd(32, 1))
488 printf("----------------------------\n");
7338e3d4 489
9a5a1483
EA
490 /* if we are just verifying (that is, sendmail -t -bv), drop out now */
491 if (OpMode == MD_VERIFY)
492 return;
493
7338e3d4
EA
494 /* store hop count */
495 if (hopcnt > e->e_hopcount)
496 e->e_hopcount = hopcnt;
75a2bcaf 497
75a2bcaf 498 /* message priority */
c23930c0 499 p = hvalue("precedence", e->e_header);
7338e3d4
EA
500 if (p != NULL)
501 e->e_class = priencode(p);
5a6f454c
EA
502 if (e->e_class < 0)
503 e->e_timeoutclass = TOC_NONURGENT;
504 else if (e->e_class > 0)
505 e->e_timeoutclass = TOC_URGENT;
959cf51d 506 if (full)
418a3328 507 {
f746582a 508 e->e_msgpriority = e->e_msgsize
a0225d08
EA
509 - e->e_class * WkClassFact
510 + e->e_nrcpts * WkRecipFact;
418a3328
EA
511 }
512
513 /* message timeout priority */
514 p = hvalue("priority", e->e_header);
5a6f454c 515 if (p != NULL)
418a3328
EA
516 {
517 /* (this should be in the configuration file) */
518 if (strcasecmp(p, "urgent"))
519 e->e_timeoutclass = TOC_URGENT;
520 else if (strcasecmp(p, "normal"))
521 e->e_timeoutclass = TOC_NORMAL;
522 else if (strcasecmp(p, "non-urgent"))
523 e->e_timeoutclass = TOC_NONURGENT;
524 }
75a2bcaf 525
75a2bcaf 526 /* date message originated */
c23930c0 527 p = hvalue("posted-date", e->e_header);
75a2bcaf 528 if (p == NULL)
c23930c0 529 p = hvalue("date", e->e_header);
75a2bcaf 530 if (p != NULL)
7338e3d4 531 define('a', p, e);
4e8842eb 532
923fa8c1 533 /* check to see if this is a MIME message */
a5386d1b
EA
534 else if ((e->e_bodytype != NULL &&
535 strcasecmp(e->e_bodytype, "8BITMIME") == 0) ||
536 hvalue("MIME-Version", e->e_header) != NULL)
0b92c6af 537 {
923fa8c1 538 e->e_flags |= EF_IS_MIME;
0b92c6af
EA
539 if (HasEightBits)
540 e->e_bodytype = "8BITMIME";
541 }
a5386d1b
EA
542 else if ((p = hvalue("Content-Type", e->e_header)) != NULL)
543 {
544 /* this may be an RFC 1049 message */
545 p = strtok(p, ";/");
546 if (p == NULL || *p == ';')
547 {
548 /* yep, it is */
549 e->e_flags |= EF_DONT_MIME;
550 }
551 }
923fa8c1 552
d940893e
EA
553 /*
554 ** From person in antiquated ARPANET mode
555 ** required by UK Grey Book e-mail gateways (sigh)
556 */
557
558 if (OpMode == MD_ARPAFTP)
559 {
560 register struct hdrinfo *hi;
561
562 for (hi = HdrInfo; hi->hi_field != NULL; hi++)
563 {
564 if (bitset(H_FROM, hi->hi_flags) &&
565 (!bitset(H_RESENT, hi->hi_flags) ||
566 bitset(EF_RESENT, e->e_flags)) &&
c23930c0 567 (p = hvalue(hi->hi_field, e->e_header)) != NULL)
d940893e
EA
568 break;
569 }
570 if (hi->hi_field != NULL)
571 {
572 if (tTd(32, 2))
573 printf("eatheader: setsender(*%s == %s)\n",
574 hi->hi_field, p);
575 setsender(p, e, NULL, TRUE);
576 }
577 }
578
4e8842eb
EA
579 /*
580 ** Log collection information.
581 */
582
583# ifdef LOG
281c6540 584 if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
804e6d6d
EA
585 logsender(e, msgid);
586# endif /* LOG */
587 e->e_flags &= ~EF_LOGSENDER;
588}
589\f/*
590** LOGSENDER -- log sender information
591**
592** Parameters:
593** e -- the envelope to log
594** msgid -- the message id
595**
596** Returns:
597** none
598*/
599
179d940c 600void
804e6d6d
EA
601logsender(e, msgid)
602 register ENVELOPE *e;
603 char *msgid;
604{
8b223875 605# ifdef LOG
804e6d6d
EA
606 char *name;
607 register char *sbp;
608 register char *p;
82d343b5 609 int l;
8446c922
EA
610 char hbuf[MAXNAME + 1];
611 char sbuf[MAXLINE + 1];
612 char mbuf[MAXNAME + 1];
82d343b5
EA
613
614 /* don't allow newlines in the message-id */
615 if (msgid != NULL)
616 {
617 l = strlen(msgid);
618 if (l > sizeof mbuf - 1)
619 l = sizeof mbuf - 1;
620 bcopy(msgid, mbuf, l);
621 mbuf[l] = '\0';
622 p = mbuf;
623 while ((p = strchr(p, '\n')) != NULL)
624 *p++ = ' ';
625 }
804e6d6d
EA
626
627 if (bitset(EF_RESPONSE, e->e_flags))
628 name = "[RESPONSE]";
629 else if ((name = macvalue('_', e)) != NULL)
630 ;
389c0d5e
EA
631 else if (RealHostName == NULL)
632 name = "localhost";
804e6d6d
EA
633 else if (RealHostName[0] == '[')
634 name = RealHostName;
635 else
4e8842eb 636 {
804e6d6d
EA
637 name = hbuf;
638 (void) sprintf(hbuf, "%.80s", RealHostName);
639 if (RealHostAddr.sa.sa_family != 0)
453139c0 640 {
804e6d6d
EA
641 p = &hbuf[strlen(hbuf)];
642 (void) sprintf(p, " (%s)",
643 anynet_ntoa(&RealHostAddr));
453139c0 644 }
804e6d6d 645 }
453139c0 646
804e6d6d 647 /* some versions of syslog only take 5 printf args */
2bbc90ee 648# if (SYSLOG_BUFSIZE) >= 256
804e6d6d
EA
649 sbp = sbuf;
650 sprintf(sbp, "from=%.200s, size=%ld, class=%d, pri=%ld, nrcpts=%d",
733f4837
EA
651 e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr,
652 e->e_msgsize, e->e_class, e->e_msgpriority, e->e_nrcpts);
804e6d6d
EA
653 sbp += strlen(sbp);
654 if (msgid != NULL)
655 {
82d343b5 656 sprintf(sbp, ", msgid=%.100s", mbuf);
07099819 657 sbp += strlen(sbp);
804e6d6d
EA
658 }
659 if (e->e_bodytype != NULL)
660 {
661 (void) sprintf(sbp, ", bodytype=%.20s", e->e_bodytype);
662 sbp += strlen(sbp);
663 }
664 p = macvalue('r', e);
665 if (p != NULL)
666 (void) sprintf(sbp, ", proto=%.20s", p);
667 syslog(LOG_INFO, "%s: %s, relay=%s",
668 e->e_id, sbuf, name);
2bbc90ee
EA
669
670# else /* short syslog buffer */
671
804e6d6d 672 syslog(LOG_INFO, "%s: from=%s",
733f4837
EA
673 e->e_id, e->e_from.q_paddr == NULL ? "<NONE>" :
674 shortenstring(e->e_from.q_paddr, 83));
804e6d6d
EA
675 syslog(LOG_INFO, "%s: size=%ld, class=%ld, pri=%ld, nrcpts=%d",
676 e->e_id, e->e_msgsize, e->e_class,
677 e->e_msgpriority, e->e_nrcpts);
678 if (msgid != NULL)
82d343b5 679 syslog(LOG_INFO, "%s: msgid=%s", e->e_id, mbuf);
3e05a82f
EA
680 sbp = sbuf;
681 sprintf(sbp, "%s:", e->e_id);
682 sbp += strlen(sbp);
804e6d6d 683 if (e->e_bodytype != NULL)
3e05a82f
EA
684 {
685 sprintf(sbp, " bodytype=%s,", e->e_bodytype);
686 sbp += strlen(sbp);
687 }
804e6d6d
EA
688 p = macvalue('r', e);
689 if (p != NULL)
3e05a82f 690 {
9c086bd3 691 sprintf(sbp, " proto=%s,", p);
3e05a82f
EA
692 sbp += strlen(sbp);
693 }
694 syslog(LOG_INFO, "%s relay=%s", sbuf, name);
2bbc90ee 695# endif
8b223875 696# endif
75a2bcaf
EA
697}
698\f/*
699** PRIENCODE -- encode external priority names into internal values.
700**
701** Parameters:
702** p -- priority in ascii.
703**
704** Returns:
705** priority as a numeric level.
706**
707** Side Effects:
708** none.
709*/
710
179d940c 711int
75a2bcaf
EA
712priencode(p)
713 char *p;
714{
a444c81b 715 register int i;
75a2bcaf 716
a444c81b 717 for (i = 0; i < NumPriorities; i++)
75a2bcaf 718 {
ed73ef1d 719 if (!strcasecmp(p, Priorities[i].pri_name))
a444c81b 720 return (Priorities[i].pri_val);
75a2bcaf 721 }
a444c81b
EA
722
723 /* unknown priority */
724 return (0);
75a2bcaf
EA
725}
726\f/*
0908f182 727** CRACKADDR -- parse an address and turn it into a macro
75a2bcaf
EA
728**
729** This doesn't actually parse the address -- it just extracts
730** it and replaces it with "$g". The parse is totally ad hoc
731** and isn't even guaranteed to leave something syntactically
732** identical to what it started with. However, it does leave
733** something semantically identical.
734**
a7948bd0
EA
735** This algorithm has been cleaned up to handle a wider range
736** of cases -- notably quoted and backslash escaped strings.
737** This modification makes it substantially better at preserving
738** the original syntax.
75a2bcaf
EA
739**
740** Parameters:
0908f182 741** addr -- the address to be cracked.
75a2bcaf
EA
742**
743** Returns:
744** a pointer to the new version.
745**
746** Side Effects:
0908f182 747** none.
75a2bcaf
EA
748**
749** Warning:
750** The return value is saved in local storage and should
751** be copied if it is to be reused.
752*/
753
754char *
0908f182
EA
755crackaddr(addr)
756 register char *addr;
75a2bcaf
EA
757{
758 register char *p;
a7948bd0
EA
759 register char c;
760 int cmtlev;
97a521ff
EA
761 int realcmtlev;
762 int anglelev, realanglelev;
a7948bd0
EA
763 int copylev;
764 bool qmode;
97a521ff
EA
765 bool realqmode;
766 bool skipping;
a7948bd0 767 bool putgmac = FALSE;
27348517 768 bool quoteit = FALSE;
d4f5b98a 769 bool gotangle = FALSE;
e7a9542d 770 bool gotcolon = FALSE;
75a2bcaf 771 register char *bp;
97a521ff 772 char *buflim;
e7a9542d
EA
773 char *bufhead;
774 char *addrhead;
8446c922 775 static char buf[MAXNAME + 1];
75a2bcaf 776
75a2bcaf 777 if (tTd(33, 1))
0908f182 778 printf("crackaddr(%s)\n", addr);
75a2bcaf 779
506fc377 780 /* strip leading spaces */
2bee003d 781 while (*addr != '\0' && isascii(*addr) && isspace(*addr))
506fc377
EA
782 addr++;
783
75a2bcaf 784 /*
a7948bd0
EA
785 ** Start by assuming we have no angle brackets. This will be
786 ** adjusted later if we find them.
75a2bcaf
EA
787 */
788
e7a9542d 789 bp = bufhead = buf;
97a521ff 790 buflim = &buf[sizeof buf - 5];
e7a9542d 791 p = addrhead = addr;
97a521ff
EA
792 copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
793 qmode = realqmode = FALSE;
a7948bd0
EA
794
795 while ((c = *p++) != '\0')
75a2bcaf 796 {
97a521ff
EA
797 /*
798 ** If the buffer is overful, go into a special "skipping"
799 ** mode that tries to keep legal syntax but doesn't actually
800 ** output things.
801 */
a7948bd0 802
97a521ff 803 skipping = bp >= buflim;
27348517 804
97a521ff
EA
805 if (copylev > 0 && !skipping)
806 *bp++ = c;
27348517 807
a7948bd0
EA
808 /* check for backslash escapes */
809 if (c == '\\')
75a2bcaf 810 {
07a399c9
EA
811 /* arrange to quote the address */
812 if (cmtlev <= 0 && !qmode)
813 quoteit = TRUE;
814
a7948bd0 815 if ((c = *p++) == '\0')
75a2bcaf 816 {
a7948bd0
EA
817 /* too far */
818 p--;
819 goto putg;
75a2bcaf 820 }
97a521ff 821 if (copylev > 0 && !skipping)
a7948bd0
EA
822 *bp++ = c;
823 goto putg;
75a2bcaf
EA
824 }
825
a7948bd0 826 /* check for quoted strings */
ae5d9ae8 827 if (c == '"' && cmtlev <= 0)
75a2bcaf 828 {
a7948bd0 829 qmode = !qmode;
97a521ff
EA
830 if (copylev > 0 && !skipping)
831 realqmode = !realqmode;
a7948bd0 832 continue;
75a2bcaf 833 }
a7948bd0
EA
834 if (qmode)
835 goto putg;
75a2bcaf 836
a7948bd0
EA
837 /* check for comments */
838 if (c == '(')
839 {
840 cmtlev++;
97a521ff
EA
841
842 /* allow space for closing paren */
843 if (!skipping)
844 {
845 buflim--;
846 realcmtlev++;
847 if (copylev++ <= 0)
848 {
849 *bp++ = ' ';
850 *bp++ = c;
851 }
852 }
a7948bd0
EA
853 }
854 if (cmtlev > 0)
75a2bcaf 855 {
a7948bd0 856 if (c == ')')
75a2bcaf 857 {
a7948bd0
EA
858 cmtlev--;
859 copylev--;
97a521ff
EA
860 if (!skipping)
861 {
862 realcmtlev--;
863 buflim++;
864 }
75a2bcaf
EA
865 }
866 continue;
867 }
97a521ff
EA
868 else if (c == ')')
869 {
870 /* syntax error: unmatched ) */
3535d73f 871 if (copylev > 0 && !skipping)
97a521ff
EA
872 bp--;
873 }
874
e7a9542d 875 /* check for group: list; syntax */
6f6c9bdd 876 if (c == ':' && anglelev <= 0 && !gotcolon && !ColonOkInAddr)
e7a9542d
EA
877 {
878 register char *q;
879
6f6c9bdd
EA
880 if (*p == ':')
881 {
882 /* special case -- :: syntax */
883 if (cmtlev <= 0 && !qmode)
884 quoteit = TRUE;
885 if (copylev > 0 && !skipping)
886 {
887 *bp++ = c;
888 *bp++ = c;
889 }
890 p++;
891 goto putg;
892 }
893
e7a9542d
EA
894 gotcolon = TRUE;
895
e7a9542d 896 bp = bufhead;
6f6c9bdd
EA
897 if (quoteit)
898 {
899 *bp++ = '"';
900
901 /* back up over the ':' and any spaces */
902 --p;
903 while (isascii(*--p) && isspace(*p))
904 continue;
905 p++;
906 }
e7a9542d
EA
907 for (q = addrhead; q < p; )
908 {
909 c = *q++;
910 if (bp < buflim)
911 {
6f6c9bdd
EA
912 if (quoteit && c == '"')
913 *bp++ = '\\';
e7a9542d
EA
914 *bp++ = c;
915 }
916 }
6f6c9bdd
EA
917 if (quoteit)
918 {
919 if (bp == &bufhead[1])
920 bp--;
921 else
922 *bp++ = '"';
923 while ((c = *p++) != ':')
924 {
925 if (bp < buflim)
926 *bp++ = c;
927 }
928 *bp++ = c;
929 }
930
931 /* any trailing white space is part of group: */
932 while (isascii(*p) && isspace(*p) && bp < buflim)
933 *bp++ = *p++;
e7a9542d 934 copylev = 0;
6f6c9bdd 935 putgmac = quoteit = FALSE;
e7a9542d
EA
936 bufhead = bp;
937 addrhead = p;
938 continue;
939 }
940
941 if (c == ';' && copylev <= 0 && !ColonOkInAddr)
942 {
e7a9542d
EA
943 if (bp < buflim)
944 *bp++ = c;
945 }
946
97a521ff 947 /* check for characters that may have to be quoted */
d4f5b98a 948 if (strchr(".'@,;:\\()[]", c) != NULL)
97a521ff
EA
949 {
950 /*
951 ** If these occur as the phrase part of a <>
952 ** construct, but are not inside of () or already
953 ** quoted, they will have to be quoted. Note that
954 ** now (but don't actually do the quoting).
955 */
956
957 if (cmtlev <= 0 && !qmode)
958 quoteit = TRUE;
959 }
75a2bcaf 960
a7948bd0
EA
961 /* check for angle brackets */
962 if (c == '<')
75a2bcaf 963 {
27348517
EA
964 register char *q;
965
d4f5b98a
EA
966 /* assume first of two angles is bogus */
967 if (gotangle)
968 quoteit = TRUE;
969 gotangle = TRUE;
970
a7948bd0 971 /* oops -- have to change our mind */
ce2496d9 972 anglelev = 1;
97a521ff 973 if (!skipping)
ce2496d9 974 realanglelev = 1;
97a521ff 975
e7a9542d 976 bp = bufhead;
27348517
EA
977 if (quoteit)
978 {
979 *bp++ = '"';
980
981 /* back up over the '<' and any spaces */
982 --p;
2bee003d 983 while (isascii(*--p) && isspace(*p))
27348517
EA
984 continue;
985 p++;
986 }
e7a9542d 987 for (q = addrhead; q < p; )
27348517
EA
988 {
989 c = *q++;
97a521ff
EA
990 if (bp < buflim)
991 {
992 if (quoteit && c == '"')
993 *bp++ = '\\';
994 *bp++ = c;
995 }
27348517
EA
996 }
997 if (quoteit)
998 {
d4f5b98a
EA
999 if (bp == &buf[1])
1000 bp--;
1001 else
1002 *bp++ = '"';
97a521ff
EA
1003 while ((c = *p++) != '<')
1004 {
1005 if (bp < buflim)
1006 *bp++ = c;
1007 }
1008 *bp++ = c;
27348517 1009 }
a7948bd0 1010 copylev = 0;
27348517 1011 putgmac = quoteit = FALSE;
a7948bd0 1012 continue;
75a2bcaf 1013 }
75a2bcaf 1014
a7948bd0
EA
1015 if (c == '>')
1016 {
97a521ff
EA
1017 if (anglelev > 0)
1018 {
1019 anglelev--;
1020 if (!skipping)
1021 {
1022 realanglelev--;
1023 buflim++;
1024 }
1025 }
1026 else if (!skipping)
1027 {
1028 /* syntax error: unmatched > */
1029 if (copylev > 0)
1030 bp--;
ce2496d9 1031 quoteit = TRUE;
97a521ff
EA
1032 continue;
1033 }
a7948bd0
EA
1034 if (copylev++ <= 0)
1035 *bp++ = c;
1036 continue;
1037 }
75a2bcaf 1038
a7948bd0
EA
1039 /* must be a real address character */
1040 putg:
1041 if (copylev <= 0 && !putgmac)
1042 {
2bee003d 1043 *bp++ = MACROEXPAND;
a7948bd0
EA
1044 *bp++ = 'g';
1045 putgmac = TRUE;
1046 }
75a2bcaf
EA
1047 }
1048
97a521ff
EA
1049 /* repair any syntactic damage */
1050 if (realqmode)
1051 *bp++ = '"';
1052 while (realcmtlev-- > 0)
1053 *bp++ = ')';
1054 while (realanglelev-- > 0)
1055 *bp++ = '>';
a7948bd0
EA
1056 *bp++ = '\0';
1057
75a2bcaf 1058 if (tTd(33, 1))
6c9bd4e1 1059 printf("crackaddr=>`%s'\n", buf);
75a2bcaf
EA
1060
1061 return (buf);
1062}
7338e3d4
EA
1063\f/*
1064** PUTHEADER -- put the header part of a message from the in-core copy
1065**
1066** Parameters:
23fafb99 1067** mci -- the connection information.
c23930c0 1068** h -- the header to put.
7338e3d4
EA
1069** e -- envelope to use.
1070**
1071** Returns:
1072** none.
1073**
1074** Side Effects:
1075** none.
1076*/
1077
1627a785
EA
1078/*
1079 * Macro for fast max (not available in e.g. DG/UX, 386/ix).
1080 */
1081#ifndef MAX
1082# define MAX(a,b) (((a)>(b))?(a):(b))
1083#endif
1084
179d940c 1085void
51d448e5 1086putheader(mci, h, e)
23fafb99 1087 register MCI *mci;
c23930c0 1088 register HDR *h;
7338e3d4
EA
1089 register ENVELOPE *e;
1090{
07b49560 1091 char buf[MAX(MAXLINE,BUFSIZ)];
07b49560 1092 char obuf[MAXLINE];
7338e3d4 1093
9f3efbed 1094 if (tTd(34, 1))
23fafb99
EA
1095 printf("--- putheader, mailer = %s ---\n",
1096 mci->mci_mailer->m_name);
9f3efbed 1097
c23930c0
EA
1098 mci->mci_flags |= MCIF_INHEADER;
1099 for (; h != NULL; h = h->h_link)
7338e3d4 1100 {
5161ccf2 1101 register char *p = h->h_value;
1dbda134 1102 extern bool bitintersect();
7338e3d4 1103
9f3efbed
EA
1104 if (tTd(34, 11))
1105 {
1106 printf(" %s: ", h->h_field);
5161ccf2 1107 xputs(p);
9f3efbed
EA
1108 }
1109
d8daa013
EA
1110 /* suppress Content-Transfer-Encoding: if we are MIMEing */
1111 if (bitset(H_CTE, h->h_flags) &&
1112 bitset(MCIF_CVT8TO7|MCIF_INMIME, mci->mci_flags))
1113 {
1114 if (tTd(34, 11))
1115 printf(" (skipped (content-transfer-encoding))\n");
1116 continue;
1117 }
1118
1119 if (bitset(MCIF_INMIME, mci->mci_flags))
1120 goto vanilla;
1121
7338e3d4 1122 if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
23fafb99 1123 !bitintersect(h->h_mflags, mci->mci_mailer->m_flags))
9f3efbed
EA
1124 {
1125 if (tTd(34, 11))
1126 printf(" (skipped)\n");
7338e3d4 1127 continue;
9f3efbed 1128 }
7338e3d4 1129
a90807d8
EA
1130 /* handle Resent-... headers specially */
1131 if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
9f3efbed
EA
1132 {
1133 if (tTd(34, 11))
1134 printf(" (skipped (resent))\n");
a90807d8 1135 continue;
9f3efbed 1136 }
a90807d8 1137
5b4215a7
EA
1138 /* suppress return receipts if requested */
1139 if (bitset(H_RECEIPTTO, h->h_flags) &&
1140 bitset(EF_NORECEIPT, e->e_flags))
1141 {
1142 if (tTd(34, 11))
1143 printf(" (skipped (receipt))\n");
1144 continue;
1145 }
1146
da9633d1 1147 /* macro expand value if generated internally */
7338e3d4
EA
1148 if (bitset(H_DEFAULT, h->h_flags))
1149 {
832e8a27 1150 expand(p, buf, sizeof buf, e);
7338e3d4
EA
1151 p = buf;
1152 if (p == NULL || *p == '\0')
da9633d1
EA
1153 {
1154 if (tTd(34, 11))
1155 printf(" (skipped -- null value)\n");
7338e3d4 1156 continue;
da9633d1 1157 }
7338e3d4
EA
1158 }
1159
da9633d1
EA
1160 if (tTd(34, 11))
1161 printf("\n");
1162
d2780a78
EA
1163 if (bitset(H_STRIPVAL, h->h_flags))
1164 {
1165 /* empty field */
1166 (void) sprintf(obuf, "%s:", h->h_field);
1167 putline(obuf, mci);
1168 }
1169 else if (bitset(H_FROM|H_RCPT, h->h_flags))
7338e3d4
EA
1170 {
1171 /* address field */
1172 bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
1173
1174 if (bitset(H_FROM, h->h_flags))
1175 oldstyle = FALSE;
23fafb99 1176 commaize(h, p, oldstyle, mci, e);
7338e3d4
EA
1177 }
1178 else
1179 {
1180 /* vanilla header line */
914bd983
EA
1181 register char *nlp;
1182
d8daa013 1183vanilla:
b6919a63 1184 (void) sprintf(obuf, "%s: ", h->h_field);
f3d8f6d6 1185 while ((nlp = strchr(p, '\n')) != NULL)
914bd983
EA
1186 {
1187 *nlp = '\0';
1188 (void) strcat(obuf, p);
1189 *nlp = '\n';
23fafb99 1190 putline(obuf, mci);
914bd983 1191 p = ++nlp;
56dad217 1192 obuf[0] = '\0';
914bd983
EA
1193 }
1194 (void) strcat(obuf, p);
23fafb99 1195 putline(obuf, mci);
7338e3d4
EA
1196 }
1197 }
7d858063
EA
1198
1199 /*
1200 ** If we are converting this to a MIME message, add the
28977dbc 1201 ** MIME headers.
7d858063
EA
1202 */
1203
8bc4f1c6 1204#if MIME8TO7
7d858063
EA
1205 if (bitset(MM_MIME8BIT, MimeMode) &&
1206 bitset(EF_HAS8BIT, e->e_flags) &&
a5386d1b 1207 !bitset(EF_DONT_MIME, e->e_flags) &&
7d858063 1208 !bitnset(M_8BITS, mci->mci_mailer->m_flags) &&
28977dbc 1209 !bitset(MCIF_CVT8TO7, mci->mci_flags))
7d858063 1210 {
28977dbc
EA
1211 if (hvalue("MIME-Version", e->e_header) == NULL)
1212 putline("MIME-Version: 1.0", mci);
1213 if (hvalue("Content-Type", e->e_header) == NULL)
1214 {
1215 sprintf(obuf, "Content-Type: text/plain; charset=%s",
3caf3b1f 1216 defcharset(e));
28977dbc
EA
1217 putline(obuf, mci);
1218 }
1219 if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL)
1220 putline("Content-Transfer-Encoding: 8bit", mci);
7d858063 1221 }
8bc4f1c6 1222#endif
7338e3d4
EA
1223}
1224\f/*
1225** COMMAIZE -- output a header field, making a comma-translated list.
1226**
1227** Parameters:
1228** h -- the header field to output.
1229** p -- the value to put in it.
7338e3d4 1230** oldstyle -- TRUE if this is an old style header.
23fafb99 1231** mci -- the connection information.
a4076aed 1232** e -- the envelope containing the message.
7338e3d4
EA
1233**
1234** Returns:
1235** none.
1236**
1237** Side Effects:
1238** outputs "p" to file "fp".
1239*/
1240
23fafb99
EA
1241void
1242commaize(h, p, oldstyle, mci, e)
7338e3d4
EA
1243 register HDR *h;
1244 register char *p;
7338e3d4 1245 bool oldstyle;
23fafb99 1246 register MCI *mci;
a4076aed 1247 register ENVELOPE *e;
7338e3d4
EA
1248{
1249 register char *obp;
1250 int opos;
c4e92f7a 1251 int omax;
7338e3d4 1252 bool firstone = TRUE;
89dd4c8f 1253 char obuf[MAXLINE + 3];
7338e3d4
EA
1254
1255 /*
1256 ** Output the address list translated by the
1257 ** mailer and with commas.
1258 */
1259
7338e3d4
EA
1260 if (tTd(14, 2))
1261 printf("commaize(%s: %s)\n", h->h_field, p);
7338e3d4 1262
7338e3d4 1263 obp = obuf;
b6919a63 1264 (void) sprintf(obp, "%s: ", h->h_field);
7338e3d4
EA
1265 opos = strlen(h->h_field) + 2;
1266 obp += opos;
e5896557
EA
1267 omax = mci->mci_mailer->m_linelimit - 2;
1268 if (omax < 0 || omax > 78)
1269 omax = 78;
7338e3d4
EA
1270
1271 /*
1272 ** Run through the list of values.
1273 */
1274
1275 while (*p != '\0')
1276 {
1277 register char *name;
85c61679 1278 register int c;
7338e3d4 1279 char savechar;
9e43a19e
EA
1280 int flags;
1281 auto int stat;
7338e3d4
EA
1282
1283 /*
1284 ** Find the end of the name. New style names
1285 ** end with a comma, old style names end with
1286 ** a space character. However, spaces do not
1287 ** necessarily delimit an old-style name -- at
1288 ** signs mean keep going.
1289 */
1290
1291 /* find end of name */
2bee003d 1292 while ((isascii(*p) && isspace(*p)) || *p == ',')
7338e3d4
EA
1293 p++;
1294 name = p;
1295 for (;;)
1296 {
9e2cf26f 1297 auto char *oldp;
217a0102 1298 char pvpbuf[PSBUFSIZE];
7338e3d4 1299
148ea694 1300 (void) prescan(p, oldstyle ? ' ' : ',', pvpbuf,
800c836f 1301 sizeof pvpbuf, &oldp, NULL);
9e2cf26f 1302 p = oldp;
7338e3d4
EA
1303
1304 /* look to see if we have an at sign */
2bee003d 1305 while (*p != '\0' && isascii(*p) && isspace(*p))
7338e3d4
EA
1306 p++;
1307
84daea29 1308 if (*p != '@')
7338e3d4
EA
1309 {
1310 p = oldp;
1311 break;
1312 }
1313 p += *p == '@' ? 1 : 2;
2bee003d 1314 while (*p != '\0' && isascii(*p) && isspace(*p))
7338e3d4
EA
1315 p++;
1316 }
1317 /* at the end of one complete name */
1318
1319 /* strip off trailing white space */
2bee003d
EA
1320 while (p >= name &&
1321 ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
7338e3d4
EA
1322 p--;
1323 if (++p == name)
1324 continue;
1325 savechar = *p;
1326 *p = '\0';
1327
1328 /* translate the name to be relative */
9e43a19e
EA
1329 flags = RF_HEADERADDR|RF_ADDDOMAIN;
1330 if (bitset(H_FROM, h->h_flags))
1331 flags |= RF_SENDERADDR;
0159023b 1332#if USERDB
47fbb920
EA
1333 else if (e->e_from.q_mailer != NULL &&
1334 bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags))
1335 {
1336 extern char *udbsender();
1337
1338 name = udbsender(name);
1339 }
1340#endif
9e43a19e 1341 stat = EX_OK;
23fafb99 1342 name = remotename(name, mci->mci_mailer, flags, &stat, e);
7338e3d4
EA
1343 if (*name == '\0')
1344 {
1345 *p = savechar;
1346 continue;
1347 }
1348
1349 /* output the name with nice formatting */
85c61679 1350 opos += strlen(name);
7338e3d4
EA
1351 if (!firstone)
1352 opos += 2;
c4e92f7a 1353 if (opos > omax && !firstone)
7338e3d4 1354 {
db860cb1 1355 (void) strcpy(obp, ",\n");
23fafb99 1356 putline(obuf, mci);
7338e3d4 1357 obp = obuf;
19decd88 1358 (void) strcpy(obp, " ");
72a1a2dd
EA
1359 opos = strlen(obp);
1360 obp += opos;
85c61679 1361 opos += strlen(name);
7338e3d4
EA
1362 }
1363 else if (!firstone)
1364 {
19decd88 1365 (void) strcpy(obp, ", ");
7338e3d4
EA
1366 obp += 2;
1367 }
1368
85c61679 1369 while ((c = *name++) != '\0' && obp < &obuf[MAXLINE])
85c61679 1370 *obp++ = c;
7338e3d4
EA
1371 firstone = FALSE;
1372 *p = savechar;
1373 }
1374 (void) strcpy(obp, "\n");
23fafb99 1375 putline(obuf, mci);
7338e3d4
EA
1376}
1377\f/*
84daea29
EA
1378** COPYHEADER -- copy header list
1379**
1380** This routine is the equivalent of newstr for header lists
7338e3d4
EA
1381**
1382** Parameters:
84daea29 1383** header -- list of header structures to copy.
7338e3d4
EA
1384**
1385** Returns:
84daea29 1386** a copy of 'header'.
7338e3d4
EA
1387**
1388** Side Effects:
1389** none.
1390*/
1391
84daea29
EA
1392HDR *
1393copyheader(header)
1394 register HDR *header;
7338e3d4 1395{
84daea29
EA
1396 register HDR *newhdr;
1397 HDR *ret;
1398 register HDR **tail = &ret;
7338e3d4 1399
84daea29
EA
1400 while (header != NULL)
1401 {
1402 newhdr = (HDR *) xalloc(sizeof(HDR));
1403 STRUCTCOPY(*header, *newhdr);
1404 *tail = newhdr;
1405 tail = &newhdr->h_link;
1406 header = header->h_link;
1407 }
1408 *tail = NULL;
1409
1410 return ret;
7338e3d4 1411}