14091Seric # include <errno.h> 24091Seric # include "sendmail.h" 34091Seric 4*4627Seric static char SccsId[] = "@(#)headers.c 3.10 10/26/81"; 54091Seric 64091Seric /* 74091Seric ** CHOMPHEADER -- process and save a header line. 84091Seric ** 94091Seric ** Called by collect and by readcf to deal with header lines. 104091Seric ** 114091Seric ** Parameters: 124091Seric ** line -- header as a text line. 134091Seric ** def -- if set, this is a default value. 144091Seric ** 154091Seric ** Returns: 164091Seric ** flags for this header. 174091Seric ** 184091Seric ** Side Effects: 194091Seric ** The header is saved on the header list. 204319Seric ** Contents of 'line' are destroyed. 214091Seric */ 224091Seric 234091Seric chompheader(line, def) 244091Seric char *line; 254091Seric bool def; 264091Seric { 274091Seric register char *p; 284091Seric register HDR *h; 294091Seric HDR **hp; 304091Seric extern bool isheader(); 314091Seric char *fname; 324091Seric char *fvalue; 334091Seric struct hdrinfo *hi; 34*4627Seric u_long mopts; 35*4627Seric extern u_long mfencode(); 364091Seric 374091Seric /* strip off trailing newline */ 384091Seric p = rindex(line, '\n'); 394091Seric if (p != NULL) 404091Seric *p = '\0'; 414091Seric 42*4627Seric /* strip off options */ 43*4627Seric mopts = 0; 44*4627Seric p = line; 45*4627Seric if (*p == '?') 46*4627Seric { 47*4627Seric /* have some */ 48*4627Seric register char *q = index(p + 1, *p); 49*4627Seric 50*4627Seric if (q != NULL) 51*4627Seric { 52*4627Seric *q++ = '\0'; 53*4627Seric mopts = mfencode(p + 1); 54*4627Seric p = q; 55*4627Seric } 56*4627Seric else 57*4627Seric syserr("chompheader: syntax error, line \"%s\"", line); 58*4627Seric } 59*4627Seric 604091Seric /* find canonical name */ 61*4627Seric fname = p; 62*4627Seric p = index(p, ':'); 634091Seric fvalue = &p[1]; 644091Seric while (isspace(*--p)) 654091Seric continue; 664091Seric *++p = '\0'; 674091Seric makelower(fname); 684091Seric 694091Seric /* strip field value on front */ 704091Seric if (*fvalue == ' ') 714091Seric fvalue++; 724091Seric 734372Seric /* hack, hack -- save From: line specially */ 744372Seric if (!def && strcmp(fname, "from") == 0) 754372Seric { 764372Seric OrigFrom = newstr(fvalue); 774372Seric return (0); 784372Seric } 794372Seric 804091Seric /* search header list for this header */ 814091Seric for (hp = &Header, h = Header; h != NULL; hp = &h->h_link, h = h->h_link) 824091Seric { 834150Seric if (strcmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags) && 844150Seric !bitset(H_FORCE, h->h_flags)) 854091Seric break; 864091Seric } 874091Seric 884091Seric /* see if it is a known type */ 894091Seric for (hi = HdrInfo; hi->hi_field != NULL; hi++) 904091Seric { 914091Seric if (strcmp(hi->hi_field, fname) == 0) 924091Seric break; 934091Seric } 944091Seric 954091Seric /* if this means "end of header" quit now */ 964091Seric if (bitset(H_EOH, hi->hi_flags)) 974091Seric return (hi->hi_flags); 984091Seric 994091Seric /* create/fill in a new node */ 1004091Seric if (h == NULL) 1014091Seric { 1024091Seric /* create a new node */ 1034091Seric *hp = h = (HDR *) xalloc(sizeof *h); 1044091Seric h->h_field = newstr(fname); 1054091Seric h->h_value = NULL; 1064091Seric h->h_link = NULL; 1074091Seric h->h_flags = hi->hi_flags; 108*4627Seric h->h_mflags = mopts | hi->hi_mflags; 1094091Seric } 1104091Seric if (def) 1114091Seric h->h_flags |= H_DEFAULT; 112*4627Seric else if (mopts == 0) 1134091Seric h->h_flags &= ~H_CHECK; 1144091Seric if (h->h_value != NULL) 1154091Seric free(h->h_value); 1164091Seric h->h_value = newstr(fvalue); 1174224Seric if (!def && GrabTo && bitset(H_ADDR, h->h_flags)) 118*4627Seric sendto(h->h_value, 0, (ADDRESS *) NULL); 1194091Seric 1204091Seric return (h->h_flags); 1214091Seric } 1224091Seric /* 1234091Seric ** HVALUE -- return value of a header. 1244091Seric ** 1254091Seric ** Only "real" fields (i.e., ones that have not been supplied 1264091Seric ** as a default) are used. 1274091Seric ** 1284091Seric ** Parameters: 1294091Seric ** field -- the field name. 1304091Seric ** 1314091Seric ** Returns: 1324091Seric ** pointer to the value part. 1334091Seric ** NULL if not found. 1344091Seric ** 1354091Seric ** Side Effects: 1364091Seric ** sets the H_USED bit in the header if found. 1374091Seric */ 1384091Seric 1394091Seric char * 1404091Seric hvalue(field) 1414091Seric char *field; 1424091Seric { 1434091Seric register HDR *h; 1444091Seric 1454091Seric for (h = Header; h != NULL; h = h->h_link) 1464091Seric { 1474091Seric if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0) 1484091Seric { 1494091Seric h->h_flags |= H_USED; 1504091Seric return (h->h_value); 1514091Seric } 1524091Seric } 1534091Seric return (NULL); 1544091Seric } 1554091Seric /* 1564091Seric ** ISHEADER -- predicate telling if argument is a header. 1574091Seric ** 1584319Seric ** A line is a header if it has a single word followed by 1594319Seric ** optional white space followed by a colon. 1604319Seric ** 1614091Seric ** Parameters: 1624091Seric ** s -- string to check for possible headerness. 1634091Seric ** 1644091Seric ** Returns: 1654091Seric ** TRUE if s is a header. 1664091Seric ** FALSE otherwise. 1674091Seric ** 1684091Seric ** Side Effects: 1694091Seric ** none. 1704319Seric ** 1714319Seric ** Bugs: 1724319Seric ** According to RFC733, there should be a newline 1734319Seric ** permitted after the word but before the colon. 1744319Seric ** We don't seem to support that..... 1754091Seric */ 1764091Seric 1774091Seric bool 1784091Seric isheader(s) 1794091Seric register char *s; 1804091Seric { 1814091Seric if (!isalnum(*s)) 1824091Seric return (FALSE); 1834091Seric while (!isspace(*s) && *s != ':') 1844091Seric s++; 1854091Seric while (isspace(*s)) 1864091Seric s++; 1874091Seric return (*s == ':'); 1884091Seric } 189