1 # include <errno.h> 2 # include "sendmail.h" 3 4 static char SccsId[] = "@(#)headers.c 3.6 09/06/81"; 5 6 /* 7 ** CHOMPHEADER -- process and save a header line. 8 ** 9 ** Called by collect and by readcf to deal with header lines. 10 ** 11 ** Parameters: 12 ** line -- header as a text line. 13 ** def -- if set, this is a default value. 14 ** 15 ** Returns: 16 ** flags for this header. 17 ** 18 ** Side Effects: 19 ** The header is saved on the header list. 20 ** Contents of 'line' are destroyed. 21 */ 22 23 chompheader(line, def) 24 char *line; 25 bool def; 26 { 27 register char *p; 28 register HDR *h; 29 HDR **hp; 30 extern bool isheader(); 31 char *fname; 32 char *fvalue; 33 struct hdrinfo *hi; 34 35 /* strip off trailing newline */ 36 p = rindex(line, '\n'); 37 if (p != NULL) 38 *p = '\0'; 39 40 /* find canonical name */ 41 fname = line; 42 p = index(line, ':'); 43 fvalue = &p[1]; 44 while (isspace(*--p)) 45 continue; 46 *++p = '\0'; 47 makelower(fname); 48 49 /* hack, hack -- save the old From: address */ 50 if (!def && strcmp(fname, "from") == 0) 51 fname = "original-from"; 52 53 /* strip field value on front */ 54 if (*fvalue == ' ') 55 fvalue++; 56 57 /* search header list for this header */ 58 for (hp = &Header, h = Header; h != NULL; hp = &h->h_link, h = h->h_link) 59 { 60 if (strcmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags) && 61 !bitset(H_FORCE, h->h_flags)) 62 break; 63 } 64 65 /* see if it is a known type */ 66 for (hi = HdrInfo; hi->hi_field != NULL; hi++) 67 { 68 if (strcmp(hi->hi_field, fname) == 0) 69 break; 70 } 71 72 /* if this means "end of header" quit now */ 73 if (bitset(H_EOH, hi->hi_flags)) 74 return (hi->hi_flags); 75 76 /* create/fill in a new node */ 77 if (h == NULL) 78 { 79 /* create a new node */ 80 *hp = h = (HDR *) xalloc(sizeof *h); 81 h->h_field = newstr(fname); 82 h->h_value = NULL; 83 h->h_link = NULL; 84 h->h_flags = hi->hi_flags; 85 h->h_mflags = hi->hi_mflags; 86 } 87 if (def) 88 h->h_flags |= H_DEFAULT; 89 else 90 h->h_flags &= ~H_CHECK; 91 if (h->h_value != NULL) 92 free(h->h_value); 93 h->h_value = newstr(fvalue); 94 if (!def && GrabTo && bitset(H_ADDR, h->h_flags)) 95 sendto(h->h_value, 0); 96 97 return (h->h_flags); 98 } 99 /* 100 ** HVALUE -- return value of a header. 101 ** 102 ** Only "real" fields (i.e., ones that have not been supplied 103 ** as a default) are used. 104 ** 105 ** Parameters: 106 ** field -- the field name. 107 ** 108 ** Returns: 109 ** pointer to the value part. 110 ** NULL if not found. 111 ** 112 ** Side Effects: 113 ** sets the H_USED bit in the header if found. 114 */ 115 116 char * 117 hvalue(field) 118 char *field; 119 { 120 register HDR *h; 121 122 for (h = Header; h != NULL; h = h->h_link) 123 { 124 if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0) 125 { 126 h->h_flags |= H_USED; 127 return (h->h_value); 128 } 129 } 130 return (NULL); 131 } 132 /* 133 ** ISHEADER -- predicate telling if argument is a header. 134 ** 135 ** A line is a header if it has a single word followed by 136 ** optional white space followed by a colon. 137 ** 138 ** Parameters: 139 ** s -- string to check for possible headerness. 140 ** 141 ** Returns: 142 ** TRUE if s is a header. 143 ** FALSE otherwise. 144 ** 145 ** Side Effects: 146 ** none. 147 ** 148 ** Bugs: 149 ** According to RFC733, there should be a newline 150 ** permitted after the word but before the colon. 151 ** We don't seem to support that..... 152 */ 153 154 bool 155 isheader(s) 156 register char *s; 157 { 158 if (!isalnum(*s)) 159 return (FALSE); 160 while (!isspace(*s) && *s != ':') 161 s++; 162 while (isspace(*s)) 163 s++; 164 return (*s == ':'); 165 } 166