1 # include <errno.h> 2 # include "sendmail.h" 3 4 static char SccsId[] = "@(#)headers.c 3.12 11/22/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 u_long mopts; 35 extern u_long mfencode(); 36 37 /* strip off trailing newline */ 38 p = rindex(line, '\n'); 39 if (p != NULL) 40 *p = '\0'; 41 42 /* strip off options */ 43 mopts = 0; 44 p = line; 45 if (*p == '?') 46 { 47 /* have some */ 48 register char *q = index(p + 1, *p); 49 50 if (q != NULL) 51 { 52 *q++ = '\0'; 53 mopts = mfencode(p + 1); 54 p = q; 55 } 56 else 57 syserr("chompheader: syntax error, line \"%s\"", line); 58 } 59 60 /* find canonical name */ 61 fname = p; 62 p = index(p, ':'); 63 fvalue = &p[1]; 64 while (isspace(*--p)) 65 continue; 66 *++p = '\0'; 67 makelower(fname); 68 69 /* strip field value on front */ 70 if (*fvalue == ' ') 71 fvalue++; 72 73 /* hack, hack -- save From: line specially */ 74 if (!def && strcmp(fname, "from") == 0) 75 { 76 OrigFrom = newstr(fvalue); 77 return (0); 78 } 79 80 /* search header list for this header */ 81 for (hp = &Header, h = Header; h != NULL; hp = &h->h_link, h = h->h_link) 82 { 83 if (strcmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags) && 84 !(bitset(H_FORCE, h->h_flags) && !QueueRun)) 85 break; 86 } 87 88 /* see if it is a known type */ 89 for (hi = HdrInfo; hi->hi_field != NULL; hi++) 90 { 91 if (strcmp(hi->hi_field, fname) == 0) 92 break; 93 } 94 95 /* if this means "end of header" quit now */ 96 if (bitset(H_EOH, hi->hi_flags)) 97 return (hi->hi_flags); 98 99 /* create/fill in a new node */ 100 if (h == NULL) 101 { 102 /* create a new node */ 103 *hp = h = (HDR *) xalloc(sizeof *h); 104 h->h_field = newstr(fname); 105 h->h_value = NULL; 106 h->h_link = NULL; 107 h->h_flags = hi->hi_flags; 108 h->h_mflags = mopts | hi->hi_mflags; 109 } 110 if (def) 111 h->h_flags |= H_DEFAULT; 112 else if (mopts == 0) 113 h->h_flags &= ~H_CHECK; 114 if (h->h_value != NULL) 115 free(h->h_value); 116 h->h_value = newstr(fvalue); 117 if (!def && GrabTo && bitset(H_ADDR, h->h_flags)) 118 sendto(h->h_value, 0, (ADDRESS *) NULL, &SendQueue); 119 120 return (h->h_flags); 121 } 122 /* 123 ** HVALUE -- return value of a header. 124 ** 125 ** Only "real" fields (i.e., ones that have not been supplied 126 ** as a default) are used. 127 ** 128 ** Parameters: 129 ** field -- the field name. 130 ** 131 ** Returns: 132 ** pointer to the value part. 133 ** NULL if not found. 134 ** 135 ** Side Effects: 136 ** sets the H_USED bit in the header if found. 137 */ 138 139 char * 140 hvalue(field) 141 char *field; 142 { 143 register HDR *h; 144 145 for (h = Header; h != NULL; h = h->h_link) 146 { 147 if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0) 148 { 149 h->h_flags |= H_USED; 150 return (h->h_value); 151 } 152 } 153 return (NULL); 154 } 155 /* 156 ** ISHEADER -- predicate telling if argument is a header. 157 ** 158 ** A line is a header if it has a single word followed by 159 ** optional white space followed by a colon. 160 ** 161 ** Parameters: 162 ** s -- string to check for possible headerness. 163 ** 164 ** Returns: 165 ** TRUE if s is a header. 166 ** FALSE otherwise. 167 ** 168 ** Side Effects: 169 ** none. 170 ** 171 ** Bugs: 172 ** According to RFC733, there should be a newline 173 ** permitted after the word but before the colon. 174 ** We don't seem to support that..... 175 */ 176 177 bool 178 isheader(s) 179 register char *s; 180 { 181 if (!isalnum(*s)) 182 return (FALSE); 183 while (!isspace(*s) && *s != ':') 184 s++; 185 while (isspace(*s)) 186 s++; 187 return (*s == ':'); 188 } 189