1 # include <errno.h> 2 # include "sendmail.h" 3 4 static char SccsId[] = "@(#)collect.c 3.20 09/07/81"; 5 6 /* 7 ** COLLECT -- read & parse message header & make temp file. 8 ** 9 ** Creates a temporary file name and copies the standard 10 ** input to that file. While it is doing it, it looks for 11 ** "From:" and "Sender:" fields to use as the from-person 12 ** (but only if the -a flag is specified). It prefers to 13 ** to use the "Sender:" field. 14 ** 15 ** MIT seems to like to produce "Sent-By:" fields instead 16 ** of "Sender:" fields. We used to catch this, but it turns 17 ** out that the "Sent-By:" field doesn't always correspond 18 ** to someone real ("___057", for instance), as required by 19 ** the protocol. So we limp by..... 20 ** 21 ** Parameters: 22 ** none 23 ** 24 ** Returns: 25 ** none. 26 ** 27 ** Side Effects: 28 ** Temp file is created and filled. 29 ** The from person may be set. 30 */ 31 32 long MsgSize; /* size of message in bytes */ 33 FILE *TempFile; /* the tempfile (after creation) */ 34 35 collect() 36 { 37 register FILE *tf; 38 char buf[MAXFIELD+1]; 39 register char *p; 40 char *xfrom; 41 extern char *hvalue(); 42 extern char *mktemp(); 43 44 /* 45 ** Create the temp file name and create the file. 46 */ 47 48 (void) mktemp(InFileName); 49 (void) close(creat(InFileName, 0600)); 50 if ((tf = fopen(InFileName, "w")) == NULL) 51 { 52 syserr("Cannot create %s", InFileName); 53 return; 54 } 55 56 /* 57 ** Try to read a UNIX-style From line 58 */ 59 60 if (fgets(buf, sizeof buf, stdin) == NULL) 61 return; 62 # ifndef NOTUNIX 63 if (strncmp(buf, "From ", 5) == 0) 64 { 65 eatfrom(buf); 66 (void) fgets(buf, sizeof buf, stdin); 67 } 68 # endif NOTUNIX 69 70 /* 71 ** Copy stdin to temp file & do message editting. 72 ** To keep certain mailers from getting confused, 73 ** and to keep the output clean, lines that look 74 ** like UNIX "From" lines are deleted in the header, 75 ** and prepended with ">" in the body. 76 */ 77 78 for (; !feof(stdin); !feof(stdin) && fgets(buf, sizeof buf, stdin)) 79 { 80 register char c; 81 extern bool isheader(); 82 83 /* see if the header is over */ 84 if (!isheader(buf)) 85 break; 86 87 /* get the rest of this field */ 88 while ((c = getc(stdin)) == ' ' || c == '\t') 89 { 90 p = &buf[strlen(buf)]; 91 *p++ = c; 92 if (fgets(p, sizeof buf - (p - buf), stdin) == NULL) 93 break; 94 } 95 if (!feof(stdin)) 96 (void) ungetc(c, stdin); 97 98 MsgSize += strlen(buf); 99 100 /* 101 ** Snarf header away. 102 */ 103 104 if (bitset(H_EOH, chompheader(buf, FALSE))) 105 break; 106 } 107 108 # ifdef DEBUG 109 if (Debug) 110 printf("EOH\n"); 111 # endif DEBUG 112 113 /* throw away a blank line */ 114 if (buf[0] == '\n') 115 (void) fgets(buf, sizeof buf, stdin); 116 117 /* 118 ** Collect the body of the message. 119 */ 120 121 for (; !feof(stdin); !feof(stdin) && fgets(buf, sizeof buf, stdin) != NULL) 122 { 123 register int i; 124 125 /* check for end-of-message */ 126 if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0')) 127 break; 128 129 # ifndef NOTUNIX 130 /* Hide UNIX-like From lines */ 131 if (strncmp(buf, "From ", 5) == 0) 132 { 133 fputs(">", tf); 134 MsgSize++; 135 } 136 # endif NOTUNIX 137 138 /* 139 ** Figure message length, output the line to the temp 140 ** file, and insert a newline if missing. 141 */ 142 143 i = strlen(buf); 144 MsgSize += i; 145 fputs(buf, tf); 146 if (buf[i - 1] != '\n') 147 fputs("\n", tf); 148 if (ferror(tf)) 149 { 150 if (errno == ENOSPC) 151 { 152 (void) freopen(InFileName, "w", tf); 153 fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf); 154 syserr("Out of disk space for temp file"); 155 } 156 else 157 syserr("Cannot write %s", InFileName); 158 (void) freopen("/dev/null", "w", tf); 159 } 160 } 161 (void) fclose(tf); 162 163 /* 164 ** Find out some information from the headers. 165 ** Examples are who is the from person & the date. 166 */ 167 168 /* from person */ 169 xfrom = hvalue("sender"); 170 if (xfrom == NULL) 171 xfrom = hvalue("original-from"); 172 if (ArpaMode != ARPA_NONE) 173 setfrom(xfrom, (char *) NULL); 174 175 /* full name of from person */ 176 p = hvalue("full-name"); 177 if (p != NULL) 178 define('x', p); 179 else 180 { 181 register char *q; 182 183 /* 184 ** Try to extract the full name from a general From: 185 ** field. We take anything which is a comment as a 186 ** first choice. Failing in that, we see if there is 187 ** a "machine readable" name (in <angle brackets>); if 188 ** so we take anything preceeding that clause. 189 ** 190 ** If we blow it here it's not all that serious. 191 */ 192 193 p = hvalue("original-from"); 194 q = index(p, '('); 195 if (q != NULL) 196 { 197 int parenlev = 0; 198 199 for (p = q; *p != '\0'; p++) 200 { 201 if (*p == '(') 202 parenlev++; 203 else if (*p == ')' && --parenlev <= 0) 204 break; 205 } 206 if (*p == ')') 207 { 208 *p = '\0'; 209 if (*++q != '\0') 210 define('x', newstr(q)); 211 *p = ')'; 212 } 213 } 214 else if ((q = index(p, '<')) != NULL) 215 { 216 char savec; 217 218 while (*--q == ' ') 219 continue; 220 while (isspace(*p)) 221 p++; 222 savec = *++q; 223 *q = '\0'; 224 if (*p != '\0') 225 define('x', newstr(p)); 226 *q = savec; 227 } 228 } 229 230 /* date message originated */ 231 p = hvalue("posted-date"); 232 if (p == NULL) 233 p = hvalue("date"); 234 if (p != NULL) 235 { 236 define('a', p); 237 /* we don't have a good way to do canonical conversion .... 238 define('d', newstr(arpatounix(p))); 239 .... so we will ignore the problem for the time being */ 240 } 241 242 if ((TempFile = fopen(InFileName, "r")) == NULL) 243 syserr("Cannot reopen %s", InFileName); 244 245 # ifdef DEBUG 246 if (Debug) 247 { 248 HDR *h; 249 extern char *capitalize(); 250 251 printf("----- collected header -----\n"); 252 for (h = Header; h != NULL; h = h->h_link) 253 printf("%s: %s\n", capitalize(h->h_field), h->h_value); 254 printf("----------------------------\n"); 255 } 256 # endif DEBUG 257 return; 258 } 259 /* 260 ** EATFROM -- chew up a UNIX style from line and process 261 ** 262 ** This does indeed make some assumptions about the format 263 ** of UNIX messages. 264 ** 265 ** Parameters: 266 ** fm -- the from line. 267 ** 268 ** Returns: 269 ** none. 270 ** 271 ** Side Effects: 272 ** extracts what information it can from the header, 273 ** such as the date. 274 */ 275 276 # ifndef NOTUNIX 277 278 char *DowList[] = 279 { 280 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL 281 }; 282 283 char *MonthList[] = 284 { 285 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 286 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 287 NULL 288 }; 289 290 eatfrom(fm) 291 char *fm; 292 { 293 register char *p; 294 register char **dt; 295 296 # ifdef DEBUG 297 if (Debug > 1) 298 printf("eatfrom(%s)\n", fm); 299 # endif DEBUG 300 301 /* find the date part */ 302 p = fm; 303 while (*p != '\0') 304 { 305 /* skip a word */ 306 while (*p != '\0' && *p != ' ') 307 *p++; 308 while (*p == ' ') 309 *p++; 310 if (!isupper(*p) || p[3] != ' ' || p[13] != ':' || p[16] != ':') 311 continue; 312 313 /* we have a possible date */ 314 for (dt = DowList; *dt != NULL; dt++) 315 if (strncmp(*dt, p, 3) == 0) 316 break; 317 if (*dt == NULL) 318 continue; 319 320 for (dt = MonthList; *dt != NULL; dt++) 321 if (strncmp(*dt, &p[4], 3) == 0) 322 break; 323 if (*dt != NULL) 324 break; 325 } 326 327 if (*p != NULL) 328 { 329 char *q; 330 331 /* we have found a date */ 332 q = xalloc(25); 333 strncpy(q, p, 25); 334 q[24] = '\0'; 335 define('d', q); 336 } 337 } 338 339 # endif NOTUNIX 340