1 # include <errno.h> 2 # include "sendmail.h" 3 4 static char SccsId[] = "@(#)collect.c 3.17 08/22/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 c; 41 extern bool isheader(); 42 char *xfrom; 43 extern char *hvalue(); 44 extern char *mktemp(); 45 extern char *capitalize(); 46 # ifdef DEBUG 47 HDR *h; 48 # endif 49 50 /* 51 ** Create the temp file name and create the file. 52 */ 53 54 (void) mktemp(InFileName); 55 (void) close(creat(InFileName, 0600)); 56 if ((tf = fopen(InFileName, "w")) == NULL) 57 { 58 syserr("Cannot create %s", InFileName); 59 return; 60 } 61 62 /* try to read a UNIX-style From line */ 63 if (fgets(buf, sizeof buf, stdin) == NULL) 64 return; 65 if (strncmp(buf, "From ", 5) == 0) 66 { 67 eatfrom(buf); 68 (void) fgets(buf, sizeof buf, stdin); 69 } 70 71 /* 72 ** Copy stdin to temp file & do message editting. 73 ** To keep certain mailers from getting confused, 74 ** and to keep the output clean, lines that look 75 ** like UNIX "From" lines are deleted in the header, 76 ** and prepended with ">" in the body. 77 */ 78 79 for (; !feof(stdin); !feof(stdin) && fgets(buf, sizeof buf, stdin)) 80 { 81 /* see if the header is over */ 82 if (!isheader(buf)) 83 break; 84 85 /* get the rest of this field */ 86 while ((c = getc(stdin)) == ' ' || c == '\t') 87 { 88 p = &buf[strlen(buf)]; 89 *p++ = c; 90 if (fgets(p, sizeof buf - (p - buf), stdin) == NULL) 91 break; 92 } 93 if (!feof(stdin)) 94 (void) ungetc(c, stdin); 95 96 MsgSize += strlen(buf); 97 98 /* 99 ** Snarf header away. 100 */ 101 102 if (bitset(H_EOH, chompheader(buf, FALSE))) 103 break; 104 } 105 106 # ifdef DEBUG 107 if (Debug) 108 printf("EOH\n"); 109 # endif DEBUG 110 111 /* throw away a blank line */ 112 if (buf[0] == '\n') 113 (void) fgets(buf, sizeof buf, stdin); 114 115 /* 116 ** Collect the body of the message. 117 */ 118 119 for (; !feof(stdin); !feof(stdin) && fgets(buf, sizeof buf, stdin) != NULL) 120 { 121 register int i; 122 123 /* check for end-of-message */ 124 if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0')) 125 break; 126 127 /* Hide UNIX-like From lines */ 128 if (strncmp(buf, "From ", 5) == 0) 129 { 130 fputs(">", tf); 131 MsgSize++; 132 } 133 134 /* 135 ** Figure message length, output the line to the temp 136 ** file, and insert a newline if missing. 137 */ 138 139 i = strlen(buf); 140 MsgSize += i; 141 fputs(buf, tf); 142 if (buf[i - 1] != '\n') 143 fputs("\n", tf); 144 if (ferror(tf)) 145 { 146 if (errno == ENOSPC) 147 { 148 (void) freopen(InFileName, "w", tf); 149 fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf); 150 syserr("Out of disk space for temp file"); 151 } 152 else 153 syserr("Cannot write %s", InFileName); 154 (void) freopen("/dev/null", "w", tf); 155 } 156 } 157 (void) fclose(tf); 158 159 /* 160 ** Find out some information from the headers. 161 ** Examples are who is the from person & the date. 162 */ 163 164 /* from person */ 165 xfrom = hvalue("sender"); 166 if (xfrom == NULL) 167 xfrom = hvalue("from"); 168 if (ArpaMode != ARPA_NONE) 169 setfrom(xfrom, NULL); 170 171 /* full name of from person */ 172 p = hvalue("full-name"); 173 if (p != NULL) 174 define('x', p); 175 176 /* date message originated */ 177 p = hvalue("posted-date"); 178 if (p == NULL) 179 p = hvalue("date"); 180 if (p != NULL) 181 { 182 define('a', p); 183 /* we don't have a good way to do canonical conversion .... 184 define('d', newstr(arpatounix(p))); 185 .... so we will ignore the problem for the time being */ 186 } 187 188 if ((TempFile = fopen(InFileName, "r")) == NULL) 189 syserr("Cannot reopen %s", InFileName); 190 191 # ifdef DEBUG 192 if (Debug) 193 { 194 printf("----- collected header -----\n"); 195 for (h = Header; h != NULL; h = h->h_link) 196 printf("%s: %s\n", capitalize(h->h_field), h->h_value); 197 printf("----------------------------\n"); 198 } 199 # endif DEBUG 200 return; 201 } 202 /* 203 ** EATFROM -- chew up a UNIX style from line and process 204 ** 205 ** This does indeed make some assumptions about the format 206 ** of UNIX messages. 207 ** 208 ** Parameters: 209 ** fm -- the from line. 210 ** 211 ** Returns: 212 ** none. 213 ** 214 ** Side Effects: 215 ** extracts what information it can from the header, 216 ** such as the date. 217 */ 218 219 char *DowList[] = 220 { 221 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL 222 }; 223 224 char *MonthList[] = 225 { 226 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 227 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 228 NULL 229 }; 230 231 eatfrom(fm) 232 char *fm; 233 { 234 register char *p; 235 register char **dt; 236 237 # ifdef DEBUG 238 if (Debug > 1) 239 printf("eatfrom(%s)\n", fm); 240 # endif DEBUG 241 242 /* find the date part */ 243 p = fm; 244 while (*p != '\0') 245 { 246 /* skip a word */ 247 while (*p != '\0' && *p != ' ') 248 *p++; 249 while (*p == ' ') 250 *p++; 251 if (!isupper(*p) || p[3] != ' ' || p[13] != ':' || p[16] != ':') 252 continue; 253 254 /* we have a possible date */ 255 for (dt = DowList; *dt != NULL; dt++) 256 if (strncmp(*dt, p, 3) == 0) 257 break; 258 if (*dt == NULL) 259 continue; 260 261 for (dt = MonthList; *dt != NULL; dt++) 262 if (strncmp(*dt, &p[4], 3) == 0) 263 break; 264 if (*dt != NULL) 265 break; 266 } 267 268 if (*p != NULL) 269 { 270 char *q; 271 272 /* we have found a date */ 273 q = xalloc(25); 274 strncpy(q, p, 25); 275 q[24] = '\0'; 276 define('d', q); 277 } 278 } 279