14091Seric # include <errno.h> 24091Seric # include "sendmail.h" 34091Seric 4*5919Seric SCCSID(@(#)headers.c 3.15 02/20/82); 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; 344627Seric u_long mopts; 354627Seric extern u_long mfencode(); 364091Seric 374091Seric /* strip off trailing newline */ 384091Seric p = rindex(line, '\n'); 394091Seric if (p != NULL) 404091Seric *p = '\0'; 414091Seric 424627Seric /* strip off options */ 434627Seric mopts = 0; 444627Seric p = line; 454627Seric if (*p == '?') 464627Seric { 474627Seric /* have some */ 484627Seric register char *q = index(p + 1, *p); 494627Seric 504627Seric if (q != NULL) 514627Seric { 524627Seric *q++ = '\0'; 534627Seric mopts = mfencode(p + 1); 544627Seric p = q; 554627Seric } 564627Seric else 574627Seric syserr("chompheader: syntax error, line \"%s\"", line); 584627Seric } 594627Seric 604091Seric /* find canonical name */ 614627Seric fname = p; 624627Seric 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 { 835187Seric if (strcmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags)) 844091Seric break; 854091Seric } 864091Seric 874091Seric /* see if it is a known type */ 884091Seric for (hi = HdrInfo; hi->hi_field != NULL; hi++) 894091Seric { 904091Seric if (strcmp(hi->hi_field, fname) == 0) 914091Seric break; 924091Seric } 934091Seric 944091Seric /* if this means "end of header" quit now */ 954091Seric if (bitset(H_EOH, hi->hi_flags)) 964091Seric return (hi->hi_flags); 974091Seric 985187Seric /* don't put timestamps in every queue run */ 995187Seric if (QueueRun && h != NULL && bitset(H_FORCE, h->h_flags)) 1005187Seric return (h->h_flags); 1015187Seric 1024091Seric /* create/fill in a new node */ 1035187Seric if (h == NULL || bitset(H_FORCE, h->h_flags)) 1044091Seric { 1054091Seric /* create a new node */ 1065187Seric h = (HDR *) xalloc(sizeof *h); 1074091Seric h->h_field = newstr(fname); 1084091Seric h->h_value = NULL; 1095187Seric h->h_link = *hp; 1104091Seric h->h_flags = hi->hi_flags; 1114627Seric h->h_mflags = mopts | hi->hi_mflags; 1125187Seric *hp = h; 1134091Seric } 1144091Seric if (def) 1154091Seric h->h_flags |= H_DEFAULT; 1164627Seric else if (mopts == 0) 1174091Seric h->h_flags &= ~H_CHECK; 1184091Seric if (h->h_value != NULL) 1194091Seric free(h->h_value); 1204091Seric h->h_value = newstr(fvalue); 121*5919Seric if (!def && GrabTo && bitset(H_RCPT, h->h_flags)) 122*5919Seric sendto(h->h_value, 0, (ADDRESS *) NULL, &SendQueue); 1234091Seric 1244091Seric return (h->h_flags); 1254091Seric } 1264091Seric /* 1274091Seric ** HVALUE -- return value of a header. 1284091Seric ** 1294091Seric ** Only "real" fields (i.e., ones that have not been supplied 1304091Seric ** as a default) are used. 1314091Seric ** 1324091Seric ** Parameters: 1334091Seric ** field -- the field name. 1344091Seric ** 1354091Seric ** Returns: 1364091Seric ** pointer to the value part. 1374091Seric ** NULL if not found. 1384091Seric ** 1394091Seric ** Side Effects: 1404091Seric ** sets the H_USED bit in the header if found. 1414091Seric */ 1424091Seric 1434091Seric char * 1444091Seric hvalue(field) 1454091Seric char *field; 1464091Seric { 1474091Seric register HDR *h; 1484091Seric 1494091Seric for (h = Header; h != NULL; h = h->h_link) 1504091Seric { 1514091Seric if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0) 1524091Seric { 1534091Seric h->h_flags |= H_USED; 1544091Seric return (h->h_value); 1554091Seric } 1564091Seric } 1574091Seric return (NULL); 1584091Seric } 1594091Seric /* 1604091Seric ** ISHEADER -- predicate telling if argument is a header. 1614091Seric ** 1624319Seric ** A line is a header if it has a single word followed by 1634319Seric ** optional white space followed by a colon. 1644319Seric ** 1654091Seric ** Parameters: 1664091Seric ** s -- string to check for possible headerness. 1674091Seric ** 1684091Seric ** Returns: 1694091Seric ** TRUE if s is a header. 1704091Seric ** FALSE otherwise. 1714091Seric ** 1724091Seric ** Side Effects: 1734091Seric ** none. 1744319Seric ** 1754319Seric ** Bugs: 1764319Seric ** According to RFC733, there should be a newline 1774319Seric ** permitted after the word but before the colon. 1784319Seric ** We don't seem to support that..... 1794091Seric */ 1804091Seric 1814091Seric bool 1824091Seric isheader(s) 1834091Seric register char *s; 1844091Seric { 1854091Seric if (!isalnum(*s)) 1864091Seric return (FALSE); 1874091Seric while (!isspace(*s) && *s != ':') 1884091Seric s++; 1894091Seric while (isspace(*s)) 1904091Seric s++; 1914091Seric return (*s == ':'); 1924091Seric } 193*5919Seric /* 194*5919Seric ** GETXPART -- extract the "signature" part of an address line. 195*5919Seric ** 196*5919Seric ** Try to extract the full name from a general address 197*5919Seric ** field. We take anything which is a comment as a 198*5919Seric ** first choice. Failing in that, we see if there is 199*5919Seric ** a "machine readable" name (in <angle brackets>); if 200*5919Seric ** so we take anything preceeding that clause. 201*5919Seric ** 202*5919Seric ** If we blow it here it's not all that serious. 203*5919Seric ** 204*5919Seric ** Parameters: 205*5919Seric ** p -- line to crack. 206*5919Seric ** 207*5919Seric ** Returns: 208*5919Seric ** signature part. 209*5919Seric ** NULL if no signature part. 210*5919Seric ** 211*5919Seric ** Side Effects: 212*5919Seric ** none. 213*5919Seric */ 214*5919Seric 215*5919Seric char * 216*5919Seric getxpart(p) 217*5919Seric register char *p; 218*5919Seric { 219*5919Seric register char *q; 220*5919Seric register char *rval = NULL; 221*5919Seric 222*5919Seric q = index(p, '('); 223*5919Seric if (q != NULL) 224*5919Seric { 225*5919Seric int parenlev = 0; 226*5919Seric 227*5919Seric for (p = q; *p != '\0'; p++) 228*5919Seric { 229*5919Seric if (*p == '(') 230*5919Seric parenlev++; 231*5919Seric else if (*p == ')' && --parenlev <= 0) 232*5919Seric break; 233*5919Seric } 234*5919Seric if (*p == ')') 235*5919Seric { 236*5919Seric *p = '\0'; 237*5919Seric if (*++q != '\0') 238*5919Seric rval = newstr(q); 239*5919Seric *p = ')'; 240*5919Seric } 241*5919Seric } 242*5919Seric else if ((q = index(p, '<')) != NULL) 243*5919Seric { 244*5919Seric char savec; 245*5919Seric 246*5919Seric while (*--q == ' ') 247*5919Seric continue; 248*5919Seric while (isspace(*p)) 249*5919Seric p++; 250*5919Seric savec = *++q; 251*5919Seric *q = '\0'; 252*5919Seric if (*p != '\0') 253*5919Seric rval = newstr(p); 254*5919Seric *q = savec; 255*5919Seric } 256*5919Seric 257*5919Seric return (rval); 258*5919Seric } 259