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