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