home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65c+IDA-1.4.4.1 / src / RCS / headers.c,v < prev    next >
Encoding:
Text File  |  1991-06-26  |  24.9 KB  |  1,339 lines

  1. head    5.15;
  2. branch    5.15.0;
  3. access;
  4. symbols
  5.     RELEASE:5.15.0.16
  6.     BETA:5.15.0.14
  7.     UICSO:5.15.0
  8.     VANILLA:5.15;
  9. locks; strict;
  10. comment    @ * @;
  11.  
  12.  
  13. 5.15
  14. date    90.06.20.08.35.51;    author paul;    state Exp;
  15. branches
  16.     5.15.0.1;
  17. next    ;
  18.  
  19. 5.15.0.1
  20. date    90.06.20.09.43.01;    author paul;    state Exp;
  21. branches;
  22. next    5.15.0.2;
  23.  
  24. 5.15.0.2
  25. date    90.10.13.18.24.14;    author paul;    state Exp;
  26. branches;
  27. next    5.15.0.3;
  28.  
  29. 5.15.0.3
  30. date    90.11.13.15.43.51;    author paul;    state Exp;
  31. branches;
  32. next    5.15.0.4;
  33.  
  34. 5.15.0.4
  35. date    90.11.24.03.05.04;    author paul;    state Exp;
  36. branches;
  37. next    5.15.0.5;
  38.  
  39. 5.15.0.5
  40. date    91.02.01.05.04.39;    author paul;    state Exp;
  41. branches;
  42. next    5.15.0.6;
  43.  
  44. 5.15.0.6
  45. date    91.02.17.04.20.59;    author paul;    state Exp;
  46. branches;
  47. next    5.15.0.7;
  48.  
  49. 5.15.0.7
  50. date    91.03.04.21.48.23;    author paul;    state Exp;
  51. branches;
  52. next    5.15.0.8;
  53.  
  54. 5.15.0.8
  55. date    91.03.05.16.46.48;    author paul;    state Exp;
  56. branches;
  57. next    5.15.0.9;
  58.  
  59. 5.15.0.9
  60. date    91.04.05.06.33.33;    author paul;    state Exp;
  61. branches;
  62. next    5.15.0.10;
  63.  
  64. 5.15.0.10
  65. date    91.04.05.14.55.15;    author paul;    state Exp;
  66. branches;
  67. next    5.15.0.11;
  68.  
  69. 5.15.0.11
  70. date    91.04.12.20.53.31;    author paul;    state Exp;
  71. branches;
  72. next    5.15.0.12;
  73.  
  74. 5.15.0.12
  75. date    91.05.18.17.28.23;    author paul;    state Exp;
  76. branches;
  77. next    5.15.0.13;
  78.  
  79. 5.15.0.13
  80. date    91.05.20.19.24.12;    author paul;    state Exp;
  81. branches;
  82. next    5.15.0.14;
  83.  
  84. 5.15.0.14
  85. date    91.05.29.19.24.10;    author paul;    state Exp;
  86. branches;
  87. next    5.15.0.15;
  88.  
  89. 5.15.0.15
  90. date    91.06.21.12.53.24;    author paul;    state Exp;
  91. branches;
  92. next    5.15.0.16;
  93.  
  94. 5.15.0.16
  95. date    91.06.26.21.43.28;    author paul;    state Exp;
  96. branches;
  97. next    ;
  98.  
  99.  
  100. desc
  101. @@
  102.  
  103.  
  104. 5.15
  105. log
  106. @5.64 Berkeley release
  107. @
  108. text
  109. @/*
  110.  * Copyright (c) 1983 Eric P. Allman
  111.  * Copyright (c) 1988 Regents of the University of California.
  112.  * All rights reserved.
  113.  *
  114.  * Redistribution and use in source and binary forms are permitted provided
  115.  * that: (1) source distributions retain this entire copyright notice and
  116.  * comment, and (2) distributions including binaries display the following
  117.  * acknowledgement:  ``This product includes software developed by the
  118.  * University of California, Berkeley and its contributors'' in the
  119.  * documentation or other materials provided with the distribution and in
  120.  * all advertising materials mentioning features or use of this software.
  121.  * Neither the name of the University nor the names of its contributors may
  122.  * be used to endorse or promote products derived from this software without
  123.  * specific prior written permission.
  124.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  125.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  126.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  127.  */
  128.  
  129. #ifndef lint
  130. static char sccsid[] = "@@(#)headers.c    5.15 (Berkeley) 6/1/90";
  131. #endif /* not lint */
  132.  
  133. # include <sys/param.h>
  134. # include <errno.h>
  135. # include "sendmail.h"
  136.  
  137. /*
  138. **  CHOMPHEADER -- process and save a header line.
  139. **
  140. **    Called by collect and by readcf to deal with header lines.
  141. **
  142. **    Parameters:
  143. **        line -- header as a text line.
  144. **        def -- if set, this is a default value.
  145. **
  146. **    Returns:
  147. **        flags for this header.
  148. **
  149. **    Side Effects:
  150. **        The header is saved on the header list.
  151. **        Contents of 'line' are destroyed.
  152. */
  153.  
  154. chompheader(line, def)
  155.     char *line;
  156.     bool def;
  157. {
  158.     register char *p;
  159.     register HDR *h;
  160.     HDR **hp;
  161.     char *fname;
  162.     char *fvalue;
  163.     struct hdrinfo *hi;
  164.     bool cond = FALSE;
  165.     BITMAP mopts;
  166.     extern char *crackaddr();
  167.  
  168.     if (tTd(31, 6))
  169.         printf("chompheader: %s\n", line);
  170.  
  171.     /* strip off options */
  172.     clrbitmap(mopts);
  173.     p = line;
  174.     if (*p == '?')
  175.     {
  176.         /* have some */
  177.         register char *q = index(p + 1, *p);
  178.         
  179.         if (q != NULL)
  180.         {
  181.             *q++ = '\0';
  182.             while (*++p != '\0')
  183.                 setbitn(*p, mopts);
  184.             p = q;
  185.         }
  186.         else
  187.             usrerr("chompheader: syntax error, line \"%s\"", line);
  188.         cond = TRUE;
  189.     }
  190.  
  191.     /* find canonical name */
  192.     fname = p;
  193.     p = index(p, ':');
  194.     if (p == NULL)
  195.     {
  196.         syserr("chompheader: syntax error, line \"%s\"", line);
  197.         return (0);
  198.     }
  199.     fvalue = &p[1];
  200.     while (isspace(*--p))
  201.         continue;
  202.     *++p = '\0';
  203.     makelower(fname);
  204.  
  205.     /* strip field value on front */
  206.     if (*fvalue == ' ')
  207.         fvalue++;
  208.  
  209.     /* see if it is a known type */
  210.     for (hi = HdrInfo; hi->hi_field != NULL; hi++)
  211.     {
  212.         if (strcmp(hi->hi_field, fname) == 0)
  213.             break;
  214.     }
  215.  
  216.     /* see if this is a resent message */
  217.     if (!def && bitset(H_RESENT, hi->hi_flags))
  218.         CurEnv->e_flags |= EF_RESENT;
  219.  
  220.     /* if this means "end of header" quit now */
  221.     if (bitset(H_EOH, hi->hi_flags))
  222.         return (hi->hi_flags);
  223.  
  224.     /* drop explicit From: if same as what we would generate -- for MH */
  225.     p = "resent-from";
  226.     if (!bitset(EF_RESENT, CurEnv->e_flags))
  227.         p += 7;
  228.     if (!def && !QueueRun && strcmp(fname, p) == 0)
  229.     {
  230.         if (CurEnv->e_from.q_paddr != NULL &&
  231.             strcmp(fvalue, CurEnv->e_from.q_paddr) == 0)
  232.             return (hi->hi_flags);
  233.     }
  234.  
  235.     /* delete default value for this header */
  236.     for (hp = &CurEnv->e_header; (h = *hp) != NULL; hp = &h->h_link)
  237.     {
  238.         if (strcmp(fname, h->h_field) == 0 &&
  239.             bitset(H_DEFAULT, h->h_flags) &&
  240.             !bitset(H_FORCE, h->h_flags))
  241.             h->h_value = NULL;
  242.     }
  243.  
  244.     /* create a new node */
  245.     h = (HDR *) xalloc(sizeof *h);
  246.     h->h_field = newstr(fname);
  247.     h->h_value = NULL;
  248.     h->h_link = NULL;
  249.     bcopy((char *) mopts, (char *) h->h_mflags, sizeof mopts);
  250.     *hp = h;
  251.     h->h_flags = hi->hi_flags;
  252.     if (def)
  253.         h->h_flags |= H_DEFAULT;
  254.     if (cond)
  255.         h->h_flags |= H_CHECK;
  256.     if (h->h_value != NULL)
  257.         free((char *) h->h_value);
  258.     h->h_value = newstr(fvalue);
  259.  
  260.     /* hack to see if this is a new format message */
  261.     if (!def && bitset(H_RCPT|H_FROM, h->h_flags) &&
  262.         (index(fvalue, ',') != NULL || index(fvalue, '(') != NULL ||
  263.          index(fvalue, '<') != NULL || index(fvalue, ';') != NULL))
  264.     {
  265.         CurEnv->e_flags &= ~EF_OLDSTYLE;
  266.     }
  267.  
  268.     return (h->h_flags);
  269. }
  270. /*
  271. **  ADDHEADER -- add a header entry to the end of the queue.
  272. **
  273. **    This bypasses the special checking of chompheader.
  274. **
  275. **    Parameters:
  276. **        field -- the name of the header field.
  277. **        value -- the value of the field.  It must be lower-cased.
  278. **        e -- the envelope to add them to.
  279. **
  280. **    Returns:
  281. **        none.
  282. **
  283. **    Side Effects:
  284. **        adds the field on the list of headers for this envelope.
  285. */
  286.  
  287. addheader(field, value, e)
  288.     char *field;
  289.     char *value;
  290.     ENVELOPE *e;
  291. {
  292.     register HDR *h;
  293.     register struct hdrinfo *hi;
  294.     HDR **hp;
  295.  
  296.     /* find info struct */
  297.     for (hi = HdrInfo; hi->hi_field != NULL; hi++)
  298.     {
  299.         if (strcmp(field, hi->hi_field) == 0)
  300.             break;
  301.     }
  302.  
  303.     /* find current place in list -- keep back pointer? */
  304.     for (hp = &e->e_header; (h = *hp) != NULL; hp = &h->h_link)
  305.     {
  306.         if (strcmp(field, h->h_field) == 0)
  307.             break;
  308.     }
  309.  
  310.     /* allocate space for new header */
  311.     h = (HDR *) xalloc(sizeof *h);
  312.     h->h_field = field;
  313.     h->h_value = newstr(value);
  314.     h->h_link = *hp;
  315.     h->h_flags = hi->hi_flags | H_DEFAULT;
  316.     clrbitmap(h->h_mflags);
  317.     *hp = h;
  318. }
  319. /*
  320. **  HVALUE -- return value of a header.
  321. **
  322. **    Only "real" fields (i.e., ones that have not been supplied
  323. **    as a default) are used.
  324. **
  325. **    Parameters:
  326. **        field -- the field name.
  327. **
  328. **    Returns:
  329. **        pointer to the value part.
  330. **        NULL if not found.
  331. **
  332. **    Side Effects:
  333. **        none.
  334. */
  335.  
  336. char *
  337. hvalue(field)
  338.     char *field;
  339. {
  340.     register HDR *h;
  341.  
  342.     for (h = CurEnv->e_header; h != NULL; h = h->h_link)
  343.     {
  344.         if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0)
  345.             return (h->h_value);
  346.     }
  347.     return (NULL);
  348. }
  349. /*
  350. **  ISHEADER -- predicate telling if argument is a header.
  351. **
  352. **    A line is a header if it has a single word followed by
  353. **    optional white space followed by a colon.
  354. **
  355. **    Parameters:
  356. **        s -- string to check for possible headerness.
  357. **
  358. **    Returns:
  359. **        TRUE if s is a header.
  360. **        FALSE otherwise.
  361. **
  362. **    Side Effects:
  363. **        none.
  364. */
  365.  
  366. bool
  367. isheader(s)
  368.     register char *s;
  369. {
  370.     while (*s > ' ' && *s != ':' && *s != '\0')
  371.         s++;
  372.  
  373.     /* following technically violates RFC822 */
  374.     while (isspace(*s))
  375.         s++;
  376.  
  377.     return (*s == ':');
  378. }
  379. /*
  380. **  EATHEADER -- run through the stored header and extract info.
  381. **
  382. **    Parameters:
  383. **        e -- the envelope to process.
  384. **
  385. **    Returns:
  386. **        none.
  387. **
  388. **    Side Effects:
  389. **        Sets a bunch of global variables from information
  390. **            in the collected header.
  391. **        Aborts the message if the hop count is exceeded.
  392. */
  393.  
  394. eatheader(e)
  395.     register ENVELOPE *e;
  396. {
  397.     register HDR *h;
  398.     register char *p;
  399.     int hopcnt = 0;
  400.  
  401.     if (tTd(32, 1))
  402.         printf("----- collected header -----\n");
  403.     for (h = e->e_header; h != NULL; h = h->h_link)
  404.     {
  405.         extern char *capitalize();
  406.  
  407.         if (tTd(32, 1))
  408.             printf("%s: %s\n", capitalize(h->h_field), h->h_value);
  409.         /* count the number of times it has been processed */
  410.         if (bitset(H_TRACE, h->h_flags))
  411.             hopcnt++;
  412.  
  413.         /* send to this person if we so desire */
  414.         if (GrabTo && bitset(H_RCPT, h->h_flags) &&
  415.             !bitset(H_DEFAULT, h->h_flags) &&
  416.             (!bitset(EF_RESENT, CurEnv->e_flags) || bitset(H_RESENT, h->h_flags)))
  417.         {
  418.             sendtolist(h->h_value, (ADDRESS *) NULL, &CurEnv->e_sendqueue);
  419.         }
  420.  
  421.         /* log the message-id */
  422. #ifdef LOG
  423.         if (!QueueRun && LogLevel > 8 && h->h_value != NULL &&
  424.             strcmp(h->h_field, "message-id") == 0)
  425.         {
  426.             char buf[MAXNAME];
  427.  
  428.             p = h->h_value;
  429.             if (bitset(H_DEFAULT, h->h_flags))
  430.             {
  431.                 expand(p, buf, &buf[sizeof buf], e);
  432.                 p = buf;
  433.             }
  434.             syslog(LOG_INFO, "%s: message-id=%s", e->e_id, p);
  435.         }
  436. #endif LOG
  437.     }
  438.     if (tTd(32, 1))
  439.         printf("----------------------------\n");
  440.  
  441.     /* store hop count */
  442.     if (hopcnt > e->e_hopcount)
  443.         e->e_hopcount = hopcnt;
  444.  
  445.     /* message priority */
  446.     p = hvalue("precedence");
  447.     if (p != NULL)
  448.         e->e_class = priencode(p);
  449.     if (!QueueRun)
  450.         e->e_msgpriority = e->e_msgsize
  451.                  - e->e_class * WkClassFact
  452.                  + e->e_nrcpts * WkRecipFact;
  453.  
  454.     /* return receipt to */
  455.     p = hvalue("return-receipt-to");
  456.     if (p != NULL)
  457.         e->e_receiptto = p;
  458.  
  459.     /* errors to */
  460.     p = hvalue("errors-to");
  461.     if (p != NULL)
  462.         sendtolist(p, (ADDRESS *) NULL, &e->e_errorqueue);
  463.  
  464.     /* from person */
  465.     if (OpMode == MD_ARPAFTP)
  466.     {
  467.         register struct hdrinfo *hi = HdrInfo;
  468.  
  469.         for (p = NULL; p == NULL && hi->hi_field != NULL; hi++)
  470.         {
  471.             if (bitset(H_FROM, hi->hi_flags))
  472.                 p = hvalue(hi->hi_field);
  473.         }
  474.         if (p != NULL)
  475.             setsender(p);
  476.     }
  477.  
  478.     /* full name of from person */
  479.     p = hvalue("full-name");
  480.     if (p != NULL)
  481.         define('x', p, e);
  482.  
  483.     /* date message originated */
  484.     p = hvalue("posted-date");
  485.     if (p == NULL)
  486.         p = hvalue("date");
  487.     if (p != NULL)
  488.     {
  489.         define('a', p, e);
  490.         /* we don't have a good way to do canonical conversion ....
  491.         define('d', newstr(arpatounix(p)), e);
  492.         .... so we will ignore the problem for the time being */
  493.     }
  494.  
  495.     /*
  496.     **  Log collection information.
  497.     */
  498.  
  499. # ifdef LOG
  500.     if (!QueueRun && LogLevel > 1)
  501.     {
  502.         char hbuf[100], *name = hbuf;
  503.  
  504.         if (RealHostName == NULL)
  505.             name = "local";
  506.         else if (RealHostName[0] == '[')
  507.             name = RealHostName;
  508.         else
  509.             (void)sprintf(hbuf, "%.90s (%s)", 
  510.                 RealHostName, inet_ntoa(RealHostAddr.sin_addr));
  511.         syslog(LOG_INFO,
  512.             "%s: from=%s, size=%ld, class=%d, received from %s\n",
  513.             CurEnv->e_id, CurEnv->e_from.q_paddr, CurEnv->e_msgsize,
  514.             CurEnv->e_class, name);
  515.     }
  516. # endif LOG
  517. }
  518. /*
  519. **  PRIENCODE -- encode external priority names into internal values.
  520. **
  521. **    Parameters:
  522. **        p -- priority in ascii.
  523. **
  524. **    Returns:
  525. **        priority as a numeric level.
  526. **
  527. **    Side Effects:
  528. **        none.
  529. */
  530.  
  531. priencode(p)
  532.     char *p;
  533. {
  534.     register int i;
  535.  
  536.     for (i = 0; i < NumPriorities; i++)
  537.     {
  538.         if (!strcasecmp(p, Priorities[i].pri_name))
  539.             return (Priorities[i].pri_val);
  540.     }
  541.  
  542.     /* unknown priority */
  543.     return (0);
  544. }
  545. /*
  546. **  CRACKADDR -- parse an address and turn it into a macro
  547. **
  548. **    This doesn't actually parse the address -- it just extracts
  549. **    it and replaces it with "$g".  The parse is totally ad hoc
  550. **    and isn't even guaranteed to leave something syntactically
  551. **    identical to what it started with.  However, it does leave
  552. **    something semantically identical.
  553. **
  554. **    The process is kind of strange.  There are a number of
  555. **    interesting cases:
  556. **        1.  comment <address> comment    ==> comment <$g> comment
  557. **        2.  address            ==> address
  558. **        3.  address (comment)        ==> $g (comment)
  559. **        4.  (comment) address        ==> (comment) $g
  560. **    And then there are the hard cases....
  561. **        5.  add (comment) ress        ==> $g (comment)
  562. **        6.  comment <address (comment)>    ==> comment <$g (comment)>
  563. **        7.    .... etc ....
  564. **
  565. **    Parameters:
  566. **        addr -- the address to be cracked.
  567. **
  568. **    Returns:
  569. **        a pointer to the new version.
  570. **
  571. **    Side Effects:
  572. **        none.
  573. **
  574. **    Warning:
  575. **        The return value is saved in local storage and should
  576. **        be copied if it is to be reused.
  577. */
  578.  
  579. char *
  580. crackaddr(addr)
  581.     register char *addr;
  582. {
  583.     register char *p;
  584.     register int i;
  585.     static char buf[MAXNAME];
  586.     char *rhs;
  587.     bool gotaddr;
  588.     register char *bp;
  589.  
  590.     if (tTd(33, 1))
  591.         printf("crackaddr(%s)\n", addr);
  592.  
  593.     (void) strcpy(buf, "");
  594.     rhs = NULL;
  595.  
  596.     /* strip leading spaces */
  597.     while (*addr != '\0' && isspace(*addr))
  598.         addr++;
  599.  
  600.     /*
  601.     **  See if we have anything in angle brackets.  If so, that is
  602.     **  the address part, and the rest is the comment.
  603.     */
  604.  
  605.     p = index(addr, '<');
  606.     if (p != NULL)
  607.     {
  608.         /* copy the beginning of the addr field to the buffer */
  609.         *p = '\0';
  610.         (void) strcpy(buf, addr);
  611.         (void) strcat(buf, "<");
  612.         *p++ = '<';
  613.  
  614.         /* skip spaces */
  615.         while (isspace(*p))
  616.             p++;
  617.  
  618.         /* find the matching right angle bracket */
  619.         addr = p;
  620.         for (i = 0; *p != '\0'; p++)
  621.         {
  622.             switch (*p)
  623.             {
  624.               case '<':
  625.                 i++;
  626.                 break;
  627.  
  628.               case '>':
  629.                 i--;
  630.                 break;
  631.             }
  632.             if (i < 0)
  633.                 break;
  634.         }
  635.  
  636.         /* p now points to the closing quote (or a null byte) */
  637.         if (*p != '\0')
  638.         {
  639.             /* make rhs point to the extra stuff at the end */
  640.             rhs = p;
  641.             *p++ = '\0';
  642.         }
  643.     }
  644.  
  645.     /*
  646.     **  Now parse the real address part.  "addr" points to the (null
  647.     **  terminated) version of what we are inerested in; rhs points
  648.     **  to the extra stuff at the end of the line, if any.
  649.     */
  650.  
  651.     p = addr;
  652.  
  653.     /* now strip out comments */
  654.     bp = &buf[strlen(buf)];
  655.     gotaddr = FALSE;
  656.     for (; *p != '\0'; p++)
  657.     {
  658.         if (*p == '(')
  659.         {
  660.             /* copy to matching close paren */
  661.             *bp++ = *p++;
  662.             for (i = 0; *p != '\0'; p++)
  663.             {
  664.                 *bp++ = *p;
  665.                 switch (*p)
  666.                 {
  667.                   case '(':
  668.                     i++;
  669.                     break;
  670.  
  671.                   case ')':
  672.                     i--;
  673.                     break;
  674.                 }
  675.                 if (i < 0)
  676.                     break;
  677.             }
  678.             continue;
  679.         }
  680.  
  681.         /*
  682.         **  If this is the first "real" character we have seen,
  683.         **  then we put the "$g" in the buffer now.
  684.         */
  685.  
  686.         if (isspace(*p))
  687.             *bp++ = *p;
  688.         else if (!gotaddr)
  689.         {
  690.             (void) strcpy(bp, "\001g");
  691.             bp += 2;
  692.             gotaddr = TRUE;
  693.         }
  694.     }
  695.  
  696.     /* hack, hack.... strip trailing blanks */
  697.     do
  698.     {
  699.         *bp-- = '\0';
  700.     } while (isspace(*bp));
  701.     bp++;
  702.  
  703.     /* put any right hand side back on */
  704.     if (rhs != NULL)
  705.     {
  706.         *rhs = '>';
  707.         (void) strcpy(bp, rhs);
  708.     }
  709.  
  710.     if (tTd(33, 1))
  711.         printf("crackaddr=>`%s'\n", buf);
  712.  
  713.     return (buf);
  714. }
  715. /*
  716. **  PUTHEADER -- put the header part of a message from the in-core copy
  717. **
  718. **    Parameters:
  719. **        fp -- file to put it on.
  720. **        m -- mailer to use.
  721. **        e -- envelope to use.
  722. **
  723. **    Returns:
  724. **        none.
  725. **
  726. **    Side Effects:
  727. **        none.
  728. */
  729.  
  730. putheader(fp, m, e)
  731.     register FILE *fp;
  732.     register MAILER *m;
  733.     register ENVELOPE *e;
  734. {
  735.     char buf[MAX(MAXFIELD,BUFSIZ)];
  736.     register HDR *h;
  737.     extern char *arpadate();
  738.     extern char *capitalize();
  739.     char obuf[MAX(MAXFIELD,MAXLINE)];
  740.  
  741.     for (h = e->e_header; h != NULL; h = h->h_link)
  742.     {
  743.         register char *p;
  744.         extern bool bitintersect();
  745.  
  746.         if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
  747.             !bitintersect(h->h_mflags, m->m_flags))
  748.             continue;
  749.  
  750.         /* handle Resent-... headers specially */
  751.         if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
  752.             continue;
  753.  
  754.         p = h->h_value;
  755.         if (bitset(H_DEFAULT, h->h_flags))
  756.         {
  757.             /* macro expand value if generated internally */
  758.             expand(p, buf, &buf[sizeof buf], e);
  759.             p = buf;
  760.             if (p == NULL || *p == '\0')
  761.                 continue;
  762.         }
  763.  
  764.         if (bitset(H_FROM|H_RCPT, h->h_flags))
  765.         {
  766.             /* address field */
  767.             bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
  768.  
  769.             if (bitset(H_FROM, h->h_flags))
  770.                 oldstyle = FALSE;
  771.             commaize(h, p, fp, oldstyle, m);
  772.         }
  773.         else
  774.         {
  775.             /* vanilla header line */
  776.             register char *nlp;
  777.  
  778.             (void) sprintf(obuf, "%s: ", capitalize(h->h_field));
  779.             while ((nlp = index(p, '\n')) != NULL)
  780.             {
  781.                 *nlp = '\0';
  782.                 (void) strcat(obuf, p);
  783.                 *nlp = '\n';
  784.                 putline(obuf, fp, m);
  785.                 p = ++nlp;
  786.                 obuf[0] = '\0';
  787.             }
  788.             (void) strcat(obuf, p);
  789.             putline(obuf, fp, m);
  790.         }
  791.     }
  792. }
  793. /*
  794. **  COMMAIZE -- output a header field, making a comma-translated list.
  795. **
  796. **    Parameters:
  797. **        h -- the header field to output.
  798. **        p -- the value to put in it.
  799. **        fp -- file to put it to.
  800. **        oldstyle -- TRUE if this is an old style header.
  801. **        m -- a pointer to the mailer descriptor.  If NULL,
  802. **            don't transform the name at all.
  803. **
  804. **    Returns:
  805. **        none.
  806. **
  807. **    Side Effects:
  808. **        outputs "p" to file "fp".
  809. */
  810.  
  811. commaize(h, p, fp, oldstyle, m)
  812.     register HDR *h;
  813.     register char *p;
  814.     FILE *fp;
  815.     bool oldstyle;
  816.     register MAILER *m;
  817. {
  818.     register char *obp;
  819.     int opos;
  820.     bool firstone = TRUE;
  821.     char obuf[MAXLINE + 3];
  822.  
  823.     /*
  824.     **  Output the address list translated by the
  825.     **  mailer and with commas.
  826.     */
  827.  
  828.     if (tTd(14, 2))
  829.         printf("commaize(%s: %s)\n", h->h_field, p);
  830.  
  831.     obp = obuf;
  832.     (void) sprintf(obp, "%s: ", capitalize(h->h_field));
  833.     opos = strlen(h->h_field) + 2;
  834.     obp += opos;
  835.  
  836.     /*
  837.     **  Run through the list of values.
  838.     */
  839.  
  840.     while (*p != '\0')
  841.     {
  842.         register char *name;
  843.         char savechar;
  844.         extern char *remotename();
  845.         extern char *DelimChar;        /* defined in prescan */
  846.  
  847.         /*
  848.         **  Find the end of the name.  New style names
  849.         **  end with a comma, old style names end with
  850.         **  a space character.  However, spaces do not
  851.         **  necessarily delimit an old-style name -- at
  852.         **  signs mean keep going.
  853.         */
  854.  
  855.         /* find end of name */
  856.         while (isspace(*p) || *p == ',')
  857.             p++;
  858.         name = p;
  859.         for (;;)
  860.         {
  861.             char *oldp;
  862.             char pvpbuf[PSBUFSIZE];
  863.             extern bool isatword();
  864.             extern char **prescan();
  865.  
  866.             (void) prescan(p, oldstyle ? ' ' : ',', pvpbuf);
  867.             p = DelimChar;
  868.  
  869.             /* look to see if we have an at sign */
  870.             oldp = p;
  871.             while (*p != '\0' && isspace(*p))
  872.                 p++;
  873.  
  874.             if (*p != '@@' && !isatword(p))
  875.             {
  876.                 p = oldp;
  877.                 break;
  878.             }
  879.             p += *p == '@@' ? 1 : 2;
  880.             while (*p != '\0' && isspace(*p))
  881.                 p++;
  882.         }
  883.         /* at the end of one complete name */
  884.  
  885.         /* strip off trailing white space */
  886.         while (p >= name && (isspace(*p) || *p == ',' || *p == '\0'))
  887.             p--;
  888.         if (++p == name)
  889.             continue;
  890.         savechar = *p;
  891.         *p = '\0';
  892.  
  893.         /* translate the name to be relative */
  894.         name = remotename(name, m, bitset(H_FROM, h->h_flags), FALSE);
  895.         if (*name == '\0')
  896.         {
  897.             *p = savechar;
  898.             continue;
  899.         }
  900.  
  901.         /* output the name with nice formatting */
  902.         opos += qstrlen(name);
  903.         if (!firstone)
  904.             opos += 2;
  905.         if (opos > 78 && !firstone)
  906.         {
  907.             (void) strcpy(obp, ",\n");
  908.             putline(obuf, fp, m);
  909.             obp = obuf;
  910.             (void) sprintf(obp, "        ");
  911.             opos = strlen(obp);
  912.             obp += opos;
  913.             opos += qstrlen(name);
  914.         }
  915.         else if (!firstone)
  916.         {
  917.             (void) sprintf(obp, ", ");
  918.             obp += 2;
  919.         }
  920.  
  921.         /* strip off quote bits as we output */
  922.         while (*name != '\0' && obp < &obuf[MAXLINE])
  923.         {
  924.             if (bitset(0200, *name))
  925.                 *obp++ = '\\';
  926.             *obp++ = *name++ & ~0200;
  927.         }
  928.         firstone = FALSE;
  929.         *p = savechar;
  930.     }
  931.     (void) strcpy(obp, "\n");
  932.     putline(obuf, fp, m);
  933. }
  934. /*
  935. **  ISATWORD -- tell if the word we are pointing to is "at".
  936. **
  937. **    Parameters:
  938. **        p -- word to check.
  939. **
  940. **    Returns:
  941. **        TRUE -- if p is the word at.
  942. **        FALSE -- otherwise.
  943. **
  944. **    Side Effects:
  945. **        none.
  946. */
  947.  
  948. bool
  949. isatword(p)
  950.     register char *p;
  951. {
  952.     extern char lower();
  953.  
  954.     if (lower(p[0]) == 'a' && lower(p[1]) == 't' &&
  955.         p[2] != '\0' && isspace(p[2]))
  956.         return (TRUE);
  957.     return (FALSE);
  958. }
  959. @
  960.  
  961.  
  962. 5.15.0.1
  963. log
  964. @IDA patches
  965. @
  966. text
  967. @d786 1
  968. a786 1
  969.         name = remotename(name, m, bitset(H_FROM, h->h_flags), FALSE, TRUE);
  970. @
  971.  
  972.  
  973. 5.15.0.2
  974. log
  975. @Extra newlines deleted from syslog statements (Bruce Lilly).  Fixed
  976. fencepost bug in third argument to expand().
  977. @
  978. text
  979. @d323 1
  980. a323 1
  981.                 expand(p, buf, &buf[(sizeof(buf)-1)], e);
  982. d404 1
  983. a404 1
  984.             "%s: from=%s, size=%ld, class=%d, received from %s",
  985. d539 1
  986. a539 1
  987.     **  terminated) version of what we are interested in; rhs points
  988. a572 4
  989.         /* keep semicolons */
  990.         if (*p == ';')
  991.             *bp++ = *p;
  992.  
  993. d650 1
  994. a650 1
  995.             expand(p, buf, &buf[(sizeof(buf)-1)], e);
  996. @
  997.  
  998.  
  999. 5.15.0.3
  1000. log
  1001. @Added #define MAX for non-SYSV machines that don't have it pre-defined.
  1002. @
  1003. text
  1004. @a625 8
  1005. /*
  1006.  * Macro for fast max (not available in e.g. DG/UX, 386/ix).
  1007.  */
  1008. #ifndef MAX
  1009. #define MAX(a,b) (((a)>(b))?(a):(b))
  1010. #endif
  1011.  
  1012.  
  1013. @
  1014.  
  1015.  
  1016. 5.15.0.4
  1017. log
  1018. @Commented out tokens following #endif statements.
  1019. @
  1020. text
  1021. @d25 3
  1022. a27 3
  1023. #include <sys/param.h>
  1024. #include <errno.h>
  1025. #include "sendmail.h"
  1026. d328 1
  1027. a328 1
  1028. #endif /* LOG */
  1029. d391 1
  1030. a391 1
  1031. #ifdef LOG
  1032. d408 1
  1033. a408 1
  1034. #endif /* LOG */
  1035. d630 1
  1036. a630 1
  1037. # define MAX(a,b) (((a)>(b))?(a):(b))
  1038. @
  1039.  
  1040.  
  1041. 5.15.0.5
  1042. log
  1043. @Delete From: header only when the sender is local.
  1044. @
  1045. text
  1046. @d123 1
  1047. a123 2
  1048.             strcmp(fvalue, CurEnv->e_from.q_paddr) == 0 &&
  1049.             CurEnv->e_from.q_mailer == LocalMailer)
  1050. @
  1051.  
  1052.  
  1053. 5.15.0.6
  1054. log
  1055. @Added static keyword for declarations of isatword() and priencode().
  1056. @
  1057. text
  1058. @a292 1
  1059.     static priencode();
  1060. a423 1
  1061. static
  1062. d768 1
  1063. a768 1
  1064.             static bool isatword();
  1065. d853 1
  1066. a853 1
  1067. static bool
  1068. @
  1069.  
  1070.  
  1071. 5.15.0.7
  1072. log
  1073. @ANSIfied.
  1074. @
  1075. text
  1076. @a28 8
  1077. #ifdef __STDC__
  1078. static priencode(const char *);
  1079. static bool isatword(const char *);
  1080. #else /* !__STDC__ */
  1081. static priencode();
  1082. static bool isatword();
  1083. #endif /* __STDC__ */
  1084.  
  1085. d58 1
  1086. a179 1
  1087. void
  1088. d182 1
  1089. a182 1
  1090.     const char *value;
  1091. d231 1
  1092. a231 1
  1093.     const char *field;
  1094. d261 1
  1095. a261 1
  1096.     register const char *s;
  1097. a286 1
  1098. void
  1099. d293 1
  1100. d299 2
  1101. d427 1
  1102. a427 1
  1103.     const char *p;
  1104. d636 1
  1105. a636 1
  1106. void
  1107. d644 2
  1108. d651 1
  1109. a717 1
  1110. void
  1111. d751 1
  1112. d770 2
  1113. d857 1
  1114. a857 1
  1115.     register const char *p;
  1116. d859 2
  1117. @
  1118.  
  1119.  
  1120. 5.15.0.8
  1121. log
  1122. @Put overly long headers (> 500 bytes) at end of message body.  Adapted
  1123. from Paul Vixie's patch.
  1124. @
  1125. text
  1126. @a284 1
  1127. **        tf -- file to append oversized headers to
  1128. a292 2
  1129. **        Appends oversized headers (> 500 bytes) to end of
  1130. **            message body.
  1131. d296 1
  1132. a296 1
  1133. eatheader(e, tf)
  1134. a297 1
  1135.     register FILE *tf;
  1136. a301 1
  1137.     bool ovfhdrs = 0;
  1138. a320 21
  1139.         if ((tf != NULL) && bitset(H_RCPT, h->h_flags) &&
  1140.             !bitset(H_DEFAULT, h->h_flags) &&
  1141.             (strlen(h->h_value) > 500))
  1142.         {
  1143.             bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
  1144.  
  1145.             if (!ovfhdrs)
  1146.             {
  1147.                 fputs("\n%%% overflow headers %%%\n", tf);
  1148.                 ovfhdrs++;
  1149.             }
  1150.  
  1151.             commaize(h, h->h_value, tf, oldstyle, LocalMailer);
  1152.             /* two notes:
  1153.              * (1) this upsets e_msgsize, but we don't care;
  1154.              * (2) newstr() is needed since this is free()'d later
  1155.              */
  1156.             h->h_value =
  1157.                 newstr("distribution:; (see end of body)");
  1158.         }
  1159.  
  1160. a339 5
  1161.  
  1162.     if (ovfhdrs)
  1163.     {
  1164.         fputs("%%% end overflow headers %%%\n", tf);
  1165.     }
  1166. @
  1167.  
  1168.  
  1169. 5.15.0.9
  1170. log
  1171. @Character set translation changes adapted from patches from Keld Simonsen
  1172. (keld@@dkuug.dk).
  1173. @
  1174. text
  1175. @a250 27
  1176. **  FINDHEADER -- locate a specific header in the envelope
  1177. **
  1178. **    Parameters:
  1179. **        field -- the name of the header field.
  1180. **        e -- the envelope to search.
  1181. **
  1182. **    Returns:
  1183. **        pointer to the header that matches.
  1184. **        NULL if not found.
  1185. **
  1186. **    Side Effects:
  1187. **        none.
  1188. */
  1189.  
  1190. HDR *
  1191. findheader(field, e)
  1192.     const char *field;
  1193.     ENVELOPE *e;
  1194. {
  1195.     register HDR *h;
  1196.  
  1197.     for (h = e->e_header; h != NULL; h = h->h_link)
  1198.         if (h->h_field && strcmp(h->h_field, field) == 0)
  1199.             return (h);
  1200.     return (NULL);
  1201. }
  1202. /*
  1203. @
  1204.  
  1205.  
  1206. 5.15.0.10
  1207. log
  1208. @Added RCS ID string
  1209. @
  1210. text
  1211. @a22 1
  1212. static char  rcsid[] = "@@(#)$Id$";
  1213. @
  1214.  
  1215.  
  1216. 5.15.0.11
  1217. log
  1218. @Boost cutoff for using overflow headers to MAXFIELD - 100.
  1219. @
  1220. text
  1221. @d23 1
  1222. a23 1
  1223. static char  rcsid[] = "@@(#)$Id: headers.c,v 5.15.0.10 1991/04/05 14:55:15 paul Exp paul $";
  1224. d322 2
  1225. a323 2
  1226. **        Appends oversized headers (> (MAXFIELD - 100) bytes)
  1227. **            to end of message body.
  1228. d356 1
  1229. a356 1
  1230.             (strlen(h->h_value) > (MAXFIELD - 100)))
  1231. @
  1232.  
  1233.  
  1234. 5.15.0.12
  1235. log
  1236. @System 5 and general improvement patches contributed by Bruce Lilly
  1237. (bruce%balilly@@broadcast.sony.com).
  1238. @
  1239. text
  1240. @d22 2
  1241. a23 2
  1242. static char sccsid[] = "@@(#)headers.c    5.15 (Berkeley) 6/1/90    %I% local";
  1243. static char  rcsid[] = "@@(#)$Id: headers.c,v 5.15.0.11 1991/04/12 20:53:31 paul Exp paul $";
  1244. d31 1
  1245. a31 1
  1246. static int priencode(const char *);
  1247. d34 1
  1248. a34 1
  1249. static int priencode();
  1250. a54 1
  1251. int
  1252. d490 1
  1253. a490 1
  1254. static int
  1255. @
  1256.  
  1257.  
  1258. 5.15.0.13
  1259. log
  1260. @For Received: headers (and others w.o. H_RCPT and H_FROM), reset $s
  1261. temporarily to DeclHostName.  DeclHostname contains the real host name
  1262. of the sender unless the name offered in the SMTP HELO command differs
  1263. from it.  It will then have the format "given (real)".
  1264. @
  1265. text
  1266. @d23 1
  1267. a23 1
  1268. static char  rcsid[] = "@@(#)$Id: headers.c,v 5.15.0.13 1991/05/20 02:42:44 paul Exp $";
  1269. a710 1
  1270.     char *macSvalue = macvalue('s', e);
  1271. a726 8
  1272.             /*
  1273.              * Use DeclHostName in headers that aren't H_RCPT
  1274.              * or H_FROM.  Restore the original value after the
  1275.              * expand().
  1276.              */
  1277.             if (!bitset(H_RCPT|H_FROM, h->h_flags) && DeclHostName)
  1278.                 define('s', DeclHostName, e);
  1279.  
  1280. a728 2
  1281.             if (!bitset(H_RCPT|H_FROM, h->h_flags) && DeclHostName)
  1282.                 define('s', macSvalue, e);
  1283. @
  1284.  
  1285.  
  1286. 5.15.0.14
  1287. log
  1288. @If RealHostName == NULL, use $s.  If that's NULL, use "local".
  1289. @
  1290. text
  1291. @d23 1
  1292. a23 1
  1293. static char  rcsid[] = "@@(#)$Id: headers.c,v 5.15.0.13 1991/05/20 19:24:12 paul Exp paul $";
  1294. d450 3
  1295. a452 6
  1296.         if (p = arpatounix(p, e))
  1297.         {
  1298.             p = newstr(p);
  1299.             *index(p, '\n') = '\0';
  1300.             define('d', p, e);
  1301.         }
  1302. d465 1
  1303. a465 4
  1304.         {
  1305.             if ((name = macvalue('s', CurEnv)) == NULL)
  1306.                 name = "local";
  1307.         }
  1308. @
  1309.  
  1310.  
  1311. 5.15.0.15
  1312. log
  1313. @Changed sccsid[].
  1314. @
  1315. text
  1316. @d22 2
  1317. a23 2
  1318. static char sccsid[] = "@@(#)headers.c    5.15 (Berkeley) 6/1/90";
  1319. static char  rcsid[] = "@@(#)$Id: headers.c,v 5.15.0.14 1991/05/29 19:24:10 paul Exp paul $";
  1320. @
  1321.  
  1322.  
  1323. 5.15.0.16
  1324. log
  1325. @Problem with bogus arpatounix return values.
  1326. @
  1327. text
  1328. @d23 1
  1329. a23 1
  1330. static char  rcsid[] = "@@(#)$Id: headers.c,v 5.15.0.15 1991/06/21 12:53:24 paul Exp paul $";
  1331. a451 2
  1332.             char *temp;
  1333.  
  1334. d453 1
  1335. a453 2
  1336.             if ((temp = index(p, '\n')) != NULL)
  1337.                 *temp = '\0';
  1338. @
  1339.