1 # include <stdio.h> 2 # include <ctype.h> 3 # include <errno.h> 4 # include "sendmail.h" 5 6 static char SccsId[] = "@(#)collect.c 3.13 08/17/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 /* check for end-of-message */ 130 if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0')) 131 break; 132 133 /* Hide UNIX-like From lines */ 134 if (strncmp(buf, "From ", 5) == 0) 135 { 136 fputs(">", tf); 137 MsgSize++; 138 } 139 MsgSize += strlen(buf); 140 fputs(buf, tf); 141 if (ferror(tf)) 142 { 143 if (errno == ENOSPC) 144 { 145 (void) freopen(InFileName, "w", tf); 146 fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf); 147 syserr("Out of disk space for temp file"); 148 } 149 else 150 syserr("Cannot write %s", InFileName); 151 (void) freopen("/dev/null", "w", tf); 152 } 153 } 154 (void) fclose(tf); 155 156 /* 157 ** Find out some information from the headers. 158 ** Examples are who is the from person & the date. 159 */ 160 161 /* from person */ 162 xfrom = hvalue("sender"); 163 if (xfrom == NULL) 164 xfrom = hvalue("from"); 165 166 /* full name of from person */ 167 p = hvalue("full-name"); 168 if (p != NULL) 169 define('x', p); 170 171 /* date message originated */ 172 p = hvalue("posted-date"); 173 if (p == NULL) 174 p = hvalue("date"); 175 if (p != NULL) 176 { 177 define('a', p); 178 /* we don't have a good way to do canonical conversion .... 179 define('d', newstr(arpatounix(p))); 180 .... so we will ignore the problem for the time being */ 181 } 182 183 if (freopen(InFileName, "r", stdin) == NULL) 184 syserr("Cannot reopen %s", InFileName); 185 186 # ifdef DEBUG 187 if (Debug) 188 { 189 printf("----- collected header -----\n"); 190 for (h = Header; h != NULL; h = h->h_link) 191 printf("%s: %s\n", capitalize(h->h_field), h->h_value); 192 printf("----------------------------\n"); 193 } 194 # endif DEBUG 195 return (ArpaFmt ? xfrom : NULL); 196 } 197 /* 198 ** EATFROM -- chew up a UNIX style from line and process 199 ** 200 ** This does indeed make some assumptions about the format 201 ** of UNIX messages. 202 ** 203 ** Parameters: 204 ** fm -- the from line. 205 ** 206 ** Returns: 207 ** none. 208 ** 209 ** Side Effects: 210 ** extracts what information it can from the header, 211 ** such as the date. 212 */ 213 214 char *MonthList[] = 215 { 216 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 217 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 218 NULL 219 }; 220 221 eatfrom(fm) 222 char *fm; 223 { 224 register char *p; 225 register char **dt; 226 227 /* find the date part */ 228 p = fm; 229 while (*p != '\0') 230 { 231 /* skip a word */ 232 while (*p != '\0' && *p != ' ') 233 *p++; 234 while (*p == ' ') 235 *p++; 236 if (!isupper(*p) || p[3] != ' ' || p[13] != ':' || p[16] != ':') 237 continue; 238 239 /* we have a possible date */ 240 for (dt = MonthList; *dt != NULL; dt++) 241 if (strncmp(*dt, p, 3) == 0) 242 break; 243 244 if (*dt != NULL) 245 break; 246 } 247 248 if (*p != NULL) 249 { 250 char *q; 251 252 /* we have found a date */ 253 q = xalloc(25); 254 strncpy(q, p, 25); 255 q[24] = '\0'; 256 define('d', q); 257 } 258 } 259