+\f/*
+** PUTHEADER -- put the header part of a message from the in-core copy
+**
+** Parameters:
+** fp -- file to put it on.
+** m -- mailer to use.
+** e -- envelope to use.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** none.
+*/
+
+putheader(fp, m, e)
+ register FILE *fp;
+ register MAILER *m;
+ register ENVELOPE *e;
+{
+ char buf[BUFSIZ];
+ register HDR *h;
+ extern char *arpadate();
+ extern char *capitalize();
+ char obuf[MAXLINE];
+ bool fullsmtp = bitset(M_FULLSMTP, m->m_flags);
+
+ for (h = e->e_header; h != NULL; h = h->h_link)
+ {
+ register char *p;
+
+ if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
+ !bitset(h->h_mflags, m->m_flags))
+ continue;
+
+ p = h->h_value;
+ if (bitset(H_DEFAULT, h->h_flags))
+ {
+ /* macro expand value if generated internally */
+ expand(p, buf, &buf[sizeof buf], e);
+ p = buf;
+ if (p == NULL || *p == '\0')
+ continue;
+ }
+
+ if (bitset(H_FROM|H_RCPT, h->h_flags))
+ {
+ /* address field */
+ bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
+
+ if (bitset(H_FROM, h->h_flags))
+ oldstyle = FALSE;
+ commaize(h, p, fp, oldstyle, m);
+ }
+ else
+ {
+ /* vanilla header line */
+ (void) sprintf(obuf, "%s: %s\n", capitalize(h->h_field), p);
+ putline(obuf, fp, fullsmtp);
+ }
+ }
+}
+\f/*
+** COMMAIZE -- output a header field, making a comma-translated list.
+**
+** Parameters:
+** h -- the header field to output.
+** p -- the value to put in it.
+** fp -- file to put it to.
+** oldstyle -- TRUE if this is an old style header.
+** m -- a pointer to the mailer descriptor. If NULL,
+** don't transform the name at all.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** outputs "p" to file "fp".
+*/
+
+commaize(h, p, fp, oldstyle, m)
+ register HDR *h;
+ register char *p;
+ FILE *fp;
+ bool oldstyle;
+ register MAILER *m;
+{
+ register char *obp;
+ int opos;
+ bool fullsmtp = FALSE;
+ bool firstone = TRUE;
+ char obuf[MAXLINE];
+
+ /*
+ ** Output the address list translated by the
+ ** mailer and with commas.
+ */
+
+# ifdef DEBUG
+ if (tTd(14, 2))
+ printf("commaize(%s: %s)\n", h->h_field, p);
+# endif DEBUG
+
+ if (m != NULL && bitset(M_FULLSMTP, m->m_flags))
+ fullsmtp = TRUE;
+
+ obp = obuf;
+ (void) sprintf(obp, "%s: ", capitalize(h->h_field));
+ opos = strlen(h->h_field) + 2;
+ obp += opos;
+
+ /*
+ ** Run through the list of values.
+ */
+
+ while (*p != '\0')
+ {
+ register char *name;
+ char savechar;
+ extern char *remotename();
+ extern char *DelimChar; /* defined in prescan */
+
+ /*
+ ** Find the end of the name. New style names
+ ** end with a comma, old style names end with
+ ** a space character. However, spaces do not
+ ** necessarily delimit an old-style name -- at
+ ** signs mean keep going.
+ */
+
+ /* find end of name */
+ while (isspace(*p) || *p == ',')
+ p++;
+ name = p;
+ for (;;)
+ {
+ char *oldp;
+ extern bool isatword();
+ extern char **prescan();
+
+ (void) prescan(p, oldstyle ? ' ' : ',');
+ p = DelimChar;
+
+ /* look to see if we have an at sign */
+ oldp = p;
+ while (*p != '\0' && isspace(*p))
+ p++;
+
+ if (*p != '@' && !isatword(p))
+ {
+ p = oldp;
+ break;
+ }
+ p += *p == '@' ? 1 : 2;
+ while (*p != '\0' && isspace(*p))
+ p++;
+ }
+ /* at the end of one complete name */
+
+ /* strip off trailing white space */
+ while (p >= name && (isspace(*p) || *p == ',' || *p == '\0'))
+ p--;
+ if (++p == name)
+ continue;
+ savechar = *p;
+ *p = '\0';
+
+ /* translate the name to be relative */
+ if (m != NULL)
+ name = remotename(name, m, bitset(H_FROM, h->h_flags));
+ if (*name == '\0')
+ {
+ *p = savechar;
+ continue;
+ }
+
+ /* output the name with nice formatting */
+ opos += qstrlen(name);
+ if (!firstone)
+ opos += 2;
+ if (opos > 78 && !firstone)
+ {
+ (void) sprintf(obp, ",\n");
+ putline(obuf, fp, fullsmtp);
+ obp = obuf;
+ (void) sprintf(obp, " ");
+ obp += strlen(obp);
+ opos = 8 + strlen(name);
+ }
+ else if (!firstone)
+ {
+ (void) sprintf(obp, ", ");
+ obp += 2;
+ }
+
+ /* strip off quote bits as we output */
+ while (*name != '\0')
+ {
+ if (bitset(0200, *name))
+ *obp++ = '\\';
+ *obp++ = *name++ & ~0200;
+ }
+ firstone = FALSE;
+ *p = savechar;
+ }
+ (void) strcpy(obp, "\n");
+ putline(obuf, fp, fullsmtp);
+}
+\f/*
+** ISATWORD -- tell if the word we are pointing to is "at".
+**
+** Parameters:
+** p -- word to check.
+**
+** Returns:
+** TRUE -- if p is the word at.
+** FALSE -- otherwise.
+**
+** Side Effects:
+** none.
+*/
+
+bool
+isatword(p)
+ register char *p;
+{
+ extern char lower();
+
+ if (lower(p[0]) == 'a' && lower(p[1]) == 't' &&
+ p[2] != '\0' && isspace(p[2]))
+ return (TRUE);
+ return (FALSE);
+}