14091Seric # include <errno.h> 24091Seric # include "sendmail.h" 34091Seric 4*4372Seric static char SccsId[] = "@(#)headers.c 3.7 09/12/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; 344091Seric 354091Seric /* strip off trailing newline */ 364091Seric p = rindex(line, '\n'); 374091Seric if (p != NULL) 384091Seric *p = '\0'; 394091Seric 404091Seric /* find canonical name */ 414091Seric fname = line; 424091Seric p = index(line, ':'); 434091Seric fvalue = &p[1]; 444091Seric while (isspace(*--p)) 454091Seric continue; 464091Seric *++p = '\0'; 474091Seric makelower(fname); 484091Seric 494091Seric /* strip field value on front */ 504091Seric if (*fvalue == ' ') 514091Seric fvalue++; 524091Seric 53*4372Seric /* hack, hack -- save From: line specially */ 54*4372Seric if (!def && strcmp(fname, "from") == 0) 55*4372Seric { 56*4372Seric OrigFrom = newstr(fvalue); 57*4372Seric return (0); 58*4372Seric } 59*4372Seric 604091Seric /* search header list for this header */ 614091Seric for (hp = &Header, h = Header; h != NULL; hp = &h->h_link, h = h->h_link) 624091Seric { 634150Seric if (strcmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags) && 644150Seric !bitset(H_FORCE, h->h_flags)) 654091Seric break; 664091Seric } 674091Seric 684091Seric /* see if it is a known type */ 694091Seric for (hi = HdrInfo; hi->hi_field != NULL; hi++) 704091Seric { 714091Seric if (strcmp(hi->hi_field, fname) == 0) 724091Seric break; 734091Seric } 744091Seric 754091Seric /* if this means "end of header" quit now */ 764091Seric if (bitset(H_EOH, hi->hi_flags)) 774091Seric return (hi->hi_flags); 784091Seric 794091Seric /* create/fill in a new node */ 804091Seric if (h == NULL) 814091Seric { 824091Seric /* create a new node */ 834091Seric *hp = h = (HDR *) xalloc(sizeof *h); 844091Seric h->h_field = newstr(fname); 854091Seric h->h_value = NULL; 864091Seric h->h_link = NULL; 874091Seric h->h_flags = hi->hi_flags; 884091Seric h->h_mflags = hi->hi_mflags; 894091Seric } 904091Seric if (def) 914091Seric h->h_flags |= H_DEFAULT; 924091Seric else 934091Seric h->h_flags &= ~H_CHECK; 944091Seric if (h->h_value != NULL) 954091Seric free(h->h_value); 964091Seric h->h_value = newstr(fvalue); 974224Seric if (!def && GrabTo && bitset(H_ADDR, h->h_flags)) 984224Seric sendto(h->h_value, 0); 994091Seric 1004091Seric return (h->h_flags); 1014091Seric } 1024091Seric /* 1034091Seric ** HVALUE -- return value of a header. 1044091Seric ** 1054091Seric ** Only "real" fields (i.e., ones that have not been supplied 1064091Seric ** as a default) are used. 1074091Seric ** 1084091Seric ** Parameters: 1094091Seric ** field -- the field name. 1104091Seric ** 1114091Seric ** Returns: 1124091Seric ** pointer to the value part. 1134091Seric ** NULL if not found. 1144091Seric ** 1154091Seric ** Side Effects: 1164091Seric ** sets the H_USED bit in the header if found. 1174091Seric */ 1184091Seric 1194091Seric char * 1204091Seric hvalue(field) 1214091Seric char *field; 1224091Seric { 1234091Seric register HDR *h; 1244091Seric 1254091Seric for (h = Header; h != NULL; h = h->h_link) 1264091Seric { 1274091Seric if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0) 1284091Seric { 1294091Seric h->h_flags |= H_USED; 1304091Seric return (h->h_value); 1314091Seric } 1324091Seric } 1334091Seric return (NULL); 1344091Seric } 1354091Seric /* 1364091Seric ** ISHEADER -- predicate telling if argument is a header. 1374091Seric ** 1384319Seric ** A line is a header if it has a single word followed by 1394319Seric ** optional white space followed by a colon. 1404319Seric ** 1414091Seric ** Parameters: 1424091Seric ** s -- string to check for possible headerness. 1434091Seric ** 1444091Seric ** Returns: 1454091Seric ** TRUE if s is a header. 1464091Seric ** FALSE otherwise. 1474091Seric ** 1484091Seric ** Side Effects: 1494091Seric ** none. 1504319Seric ** 1514319Seric ** Bugs: 1524319Seric ** According to RFC733, there should be a newline 1534319Seric ** permitted after the word but before the colon. 1544319Seric ** We don't seem to support that..... 1554091Seric */ 1564091Seric 1574091Seric bool 1584091Seric isheader(s) 1594091Seric register char *s; 1604091Seric { 1614091Seric if (!isalnum(*s)) 1624091Seric return (FALSE); 1634091Seric while (!isspace(*s) && *s != ':') 1644091Seric s++; 1654091Seric while (isspace(*s)) 1664091Seric s++; 1674091Seric return (*s == ':'); 1684091Seric } 169