14091Seric # include <errno.h> 24091Seric # include "sendmail.h" 34091Seric 4*7677Seric SCCSID(@(#)headers.c 3.22 08/08/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 37*7677Seric # ifdef DEBUG 38*7677Seric if (tTd(31, 6)) 39*7677Seric printf("chompheader: %s\n", line); 40*7677Seric # endif DEBUG 41*7677Seric 424091Seric /* strip off trailing newline */ 434091Seric p = rindex(line, '\n'); 444091Seric if (p != NULL) 454091Seric *p = '\0'; 464091Seric 474627Seric /* strip off options */ 484627Seric mopts = 0; 494627Seric p = line; 504627Seric if (*p == '?') 514627Seric { 524627Seric /* have some */ 534627Seric register char *q = index(p + 1, *p); 544627Seric 554627Seric if (q != NULL) 564627Seric { 574627Seric *q++ = '\0'; 584627Seric mopts = mfencode(p + 1); 594627Seric p = q; 604627Seric } 614627Seric else 624627Seric syserr("chompheader: syntax error, line \"%s\"", line); 634627Seric } 644627Seric 654091Seric /* find canonical name */ 664627Seric fname = p; 674627Seric p = index(p, ':'); 684091Seric fvalue = &p[1]; 694091Seric while (isspace(*--p)) 704091Seric continue; 714091Seric *++p = '\0'; 724091Seric makelower(fname); 734091Seric 744091Seric /* strip field value on front */ 754091Seric if (*fvalue == ' ') 764091Seric fvalue++; 774091Seric 784372Seric /* hack, hack -- save From: line specially */ 796051Seric if (!def && !QueueRun && strcmp(fname, "from") == 0) 804372Seric { 816908Seric CurEnv->e_origfrom = newstr(fvalue); 824372Seric return (0); 834372Seric } 844372Seric 854091Seric /* search header list for this header */ 866908Seric for (hp = &CurEnv->e_header, h = CurEnv->e_header; h != NULL; hp = &h->h_link, h = h->h_link) 874091Seric { 885187Seric if (strcmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags)) 894091Seric break; 904091Seric } 914091Seric 924091Seric /* see if it is a known type */ 934091Seric for (hi = HdrInfo; hi->hi_field != NULL; hi++) 944091Seric { 954091Seric if (strcmp(hi->hi_field, fname) == 0) 964091Seric break; 974091Seric } 984091Seric 994091Seric /* if this means "end of header" quit now */ 1004091Seric if (bitset(H_EOH, hi->hi_flags)) 1014091Seric return (hi->hi_flags); 1024091Seric 1035187Seric /* don't put timestamps in every queue run */ 1045187Seric if (QueueRun && h != NULL && bitset(H_FORCE, h->h_flags)) 1055187Seric return (h->h_flags); 1065187Seric 1077365Seric /* count Mail-From: lines to avoid loops (simulate hop counts) */ 1087365Seric if (strcmp(fname, "mail-from") == 0) 1097365Seric HopCount++; 1107365Seric 1114091Seric /* create/fill in a new node */ 1125187Seric if (h == NULL || bitset(H_FORCE, h->h_flags)) 1134091Seric { 1144091Seric /* create a new node */ 1155187Seric h = (HDR *) xalloc(sizeof *h); 1164091Seric h->h_field = newstr(fname); 1174091Seric h->h_value = NULL; 1185187Seric h->h_link = *hp; 1194091Seric h->h_flags = hi->hi_flags; 1204627Seric h->h_mflags = mopts | hi->hi_mflags; 1215187Seric *hp = h; 1224091Seric } 1234091Seric if (def) 1244091Seric h->h_flags |= H_DEFAULT; 1254627Seric else if (mopts == 0) 1264091Seric h->h_flags &= ~H_CHECK; 1274091Seric if (h->h_value != NULL) 1284091Seric free(h->h_value); 1294091Seric h->h_value = newstr(fvalue); 1305919Seric if (!def && GrabTo && bitset(H_RCPT, h->h_flags)) 1316908Seric sendto(h->h_value, 0, (ADDRESS *) NULL, &CurEnv->e_sendqueue); 1324091Seric 1335937Seric /* hack to see if this is a new format message */ 1345937Seric if (bitset(H_RCPT, h->h_flags) && 1355937Seric (index(fvalue, ',') != NULL || index(fvalue, '(') != NULL || 1365937Seric index(fvalue, '<') != NULL)) 1376908Seric CurEnv->e_oldstyle = FALSE; 1385937Seric 1394091Seric return (h->h_flags); 1404091Seric } 1414091Seric /* 1426980Seric ** ADDHEADER -- add a header entry to the end of the queue. 1436980Seric ** 1446980Seric ** This bypasses the special checking of chompheader. 1456980Seric ** 1466980Seric ** Parameters: 1476980Seric ** field -- the name of the header field. 1486980Seric ** value -- the value of the field. It must be lower-cased. 1496980Seric ** e -- the envelope to add them to. 1506980Seric ** 1516980Seric ** Returns: 1526980Seric ** none. 1536980Seric ** 1546980Seric ** Side Effects: 1556980Seric ** adds the field on the list of headers for this envelope. 1566980Seric */ 1576980Seric 1586980Seric addheader(field, value, e) 1596980Seric char *field; 1606980Seric char *value; 1616980Seric ENVELOPE *e; 1626980Seric { 1636980Seric register HDR *h; 1646980Seric register struct hdrinfo *hi; 1656980Seric HDR **hp; 1666980Seric 1676980Seric /* find info struct */ 1686980Seric for (hi = HdrInfo; hi->hi_field != NULL; hi++) 1696980Seric { 1706980Seric if (strcmp(field, hi->hi_field) == 0) 1716980Seric break; 1726980Seric } 1736980Seric 1746980Seric /* find current place in list -- keep back pointer? */ 1756980Seric for (hp = &e->e_header; (h = *hp) != NULL; hp = &h->h_link) 1766980Seric { 1776980Seric if (strcmp(field, h->h_field) == 0) 1786980Seric break; 1796980Seric } 1806980Seric 1816980Seric /* allocate space for new header */ 1826980Seric h = (HDR *) xalloc(sizeof *h); 1836980Seric h->h_field = field; 1846980Seric h->h_value = newstr(value); 1857368Seric h->h_link = *hp; 1866980Seric h->h_flags = hi->hi_flags | H_DEFAULT; 1876980Seric h->h_mflags = hi->hi_mflags; 1886980Seric *hp = h; 1896980Seric } 1906980Seric /* 1914091Seric ** HVALUE -- return value of a header. 1924091Seric ** 1934091Seric ** Only "real" fields (i.e., ones that have not been supplied 1944091Seric ** as a default) are used. 1954091Seric ** 1964091Seric ** Parameters: 1974091Seric ** field -- the field name. 1984091Seric ** 1994091Seric ** Returns: 2004091Seric ** pointer to the value part. 2014091Seric ** NULL if not found. 2024091Seric ** 2034091Seric ** Side Effects: 2044091Seric ** sets the H_USED bit in the header if found. 2054091Seric */ 2064091Seric 2074091Seric char * 2084091Seric hvalue(field) 2094091Seric char *field; 2104091Seric { 2114091Seric register HDR *h; 2124091Seric 2136908Seric for (h = CurEnv->e_header; h != NULL; h = h->h_link) 2144091Seric { 2154091Seric if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0) 2164091Seric { 2174091Seric h->h_flags |= H_USED; 2184091Seric return (h->h_value); 2194091Seric } 2204091Seric } 2214091Seric return (NULL); 2224091Seric } 2234091Seric /* 224*7677Seric ** HRVALUE -- return pointer to header descriptor. 225*7677Seric ** 226*7677Seric ** Like hvalue except returns header descriptor block and isn't 227*7677Seric ** picky about "real" headers. 228*7677Seric ** 229*7677Seric ** Parameters: 230*7677Seric ** field -- name of field we are interested in. 231*7677Seric ** 232*7677Seric ** Returns: 233*7677Seric ** pointer to header descriptor. 234*7677Seric ** 235*7677Seric ** Side Effects: 236*7677Seric ** none. 237*7677Seric */ 238*7677Seric 239*7677Seric HDR * 240*7677Seric hrvalue(field) 241*7677Seric char *field; 242*7677Seric { 243*7677Seric register HDR *h; 244*7677Seric 245*7677Seric for (h = CurEnv->e_header; h != NULL; h = h->h_link) 246*7677Seric { 247*7677Seric if (strcmp(h->h_field, field) == 0) 248*7677Seric return (h); 249*7677Seric } 250*7677Seric return (NULL); 251*7677Seric } 252*7677Seric /* 2534091Seric ** ISHEADER -- predicate telling if argument is a header. 2544091Seric ** 2554319Seric ** A line is a header if it has a single word followed by 2564319Seric ** optional white space followed by a colon. 2574319Seric ** 2584091Seric ** Parameters: 2594091Seric ** s -- string to check for possible headerness. 2604091Seric ** 2614091Seric ** Returns: 2624091Seric ** TRUE if s is a header. 2634091Seric ** FALSE otherwise. 2644091Seric ** 2654091Seric ** Side Effects: 2664091Seric ** none. 2674319Seric ** 2684319Seric ** Bugs: 2694319Seric ** According to RFC733, there should be a newline 2704319Seric ** permitted after the word but before the colon. 2714319Seric ** We don't seem to support that..... 2724091Seric */ 2734091Seric 2744091Seric bool 2754091Seric isheader(s) 2764091Seric register char *s; 2774091Seric { 2784091Seric if (!isalnum(*s)) 2794091Seric return (FALSE); 2804091Seric while (!isspace(*s) && *s != ':') 2814091Seric s++; 2824091Seric while (isspace(*s)) 2834091Seric s++; 2844091Seric return (*s == ':'); 2854091Seric } 2865919Seric /* 2875919Seric ** GETXPART -- extract the "signature" part of an address line. 2885919Seric ** 2895919Seric ** Try to extract the full name from a general address 2905919Seric ** field. We take anything which is a comment as a 2915919Seric ** first choice. Failing in that, we see if there is 2925919Seric ** a "machine readable" name (in <angle brackets>); if 2935919Seric ** so we take anything preceeding that clause. 2945919Seric ** 2955919Seric ** If we blow it here it's not all that serious. 2965919Seric ** 2975919Seric ** Parameters: 2985919Seric ** p -- line to crack. 2995919Seric ** 3005919Seric ** Returns: 3015919Seric ** signature part. 3025919Seric ** NULL if no signature part. 3035919Seric ** 3045919Seric ** Side Effects: 3055919Seric ** none. 3065919Seric */ 3075919Seric 3085919Seric char * 3095919Seric getxpart(p) 3105919Seric register char *p; 3115919Seric { 3125919Seric register char *q; 3135919Seric register char *rval = NULL; 3145919Seric 3155919Seric q = index(p, '('); 3165919Seric if (q != NULL) 3175919Seric { 3185919Seric int parenlev = 0; 3195919Seric 3205919Seric for (p = q; *p != '\0'; p++) 3215919Seric { 3225919Seric if (*p == '(') 3235919Seric parenlev++; 3245919Seric else if (*p == ')' && --parenlev <= 0) 3255919Seric break; 3265919Seric } 3275919Seric if (*p == ')') 3285919Seric { 3295919Seric *p = '\0'; 3305919Seric if (*++q != '\0') 3315919Seric rval = newstr(q); 3325919Seric *p = ')'; 3335919Seric } 3345919Seric } 3355919Seric else if ((q = index(p, '<')) != NULL) 3365919Seric { 3375919Seric char savec; 3385919Seric 3395919Seric while (*--q == ' ') 3405919Seric continue; 3415919Seric while (isspace(*p)) 3425919Seric p++; 3435919Seric savec = *++q; 3445919Seric *q = '\0'; 3455919Seric if (*p != '\0') 3465919Seric rval = newstr(p); 3475919Seric *q = savec; 3485919Seric } 3495919Seric 3505919Seric return (rval); 3515919Seric } 352