1: # include <errno.h> 2: # include "sendmail.h" 3: 4: SCCSID(@(#)collect.c 4.1 7/25/83); 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. Leading UNIX-style "From" lines are 11: ** stripped off (after important information is extracted). 12: ** 13: ** Parameters: 14: ** sayok -- if set, give an ARPANET style message 15: ** to say we are ready to collect input. 16: ** 17: ** Returns: 18: ** none. 19: ** 20: ** Side Effects: 21: ** Temp file is created and filled. 22: ** The from person may be set. 23: */ 24: 25: collect(sayok) 26: bool sayok; 27: { 28: register FILE *tf; 29: char buf[MAXFIELD+2]; 30: register char *p; 31: extern char *hvalue(); 32: 33: /* 34: ** Create the temp file name and create the file. 35: */ 36: 37: CurEnv->e_df = newstr(queuename(CurEnv, 'd')); 38: if ((tf = dfopen(CurEnv->e_df, "w")) == NULL) 39: { 40: syserr("Cannot create %s", CurEnv->e_df); 41: NoReturn = TRUE; 42: finis(); 43: } 44: (void) chmod(CurEnv->e_df, FileMode); 45: 46: /* 47: ** Tell ARPANET to go ahead. 48: */ 49: 50: if (sayok) 51: message("354", "Enter mail, end with \".\" on a line by itself"); 52: 53: /* 54: ** Try to read a UNIX-style From line 55: */ 56: 57: if (sfgets(buf, sizeof buf, InChannel) == NULL) 58: return; 59: fixcrlf(buf, FALSE); 60: # ifndef NOTUNIX 61: if (!SaveFrom && strncmp(buf, "From ", 5) == 0) 62: { 63: eatfrom(buf); 64: (void) sfgets(buf, sizeof buf, InChannel); 65: fixcrlf(buf, FALSE); 66: } 67: # endif NOTUNIX 68: 69: /* 70: ** Copy InChannel to temp file & do message editing. 71: ** To keep certain mailers from getting confused, 72: ** and to keep the output clean, lines that look 73: ** like UNIX "From" lines are deleted in the header. 74: */ 75: 76: for (; !feof(InChannel); !feof(InChannel) && !ferror(InChannel) && 77: sfgets(buf, MAXFIELD, InChannel) != NULL) 78: { 79: register char c; 80: extern bool isheader(); 81: 82: /* if the line is too long, throw the rest away */ 83: if (index(buf, '\n') == NULL) 84: { 85: while ((c = getc(InChannel)) != '\n') 86: continue; 87: /* give an error? */ 88: } 89: 90: fixcrlf(buf, TRUE); 91: 92: /* see if the header is over */ 93: if (!isheader(buf)) 94: break; 95: 96: /* get the rest of this field */ 97: while ((c = getc(InChannel)) == ' ' || c == '\t') 98: { 99: p = &buf[strlen(buf)]; 100: *p++ = '\n'; 101: *p++ = c; 102: if (sfgets(p, MAXFIELD - (p - buf), InChannel) == NULL) 103: break; 104: fixcrlf(p, TRUE); 105: } 106: if (!feof(InChannel)) 107: (void) ungetc(c, InChannel); 108: 109: CurEnv->e_msgsize += strlen(buf); 110: 111: /* 112: ** Snarf header away. 113: */ 114: 115: if (bitset(H_EOH, chompheader(buf, FALSE))) 116: break; 117: } 118: 119: # ifdef DEBUG 120: if (tTd(30, 1)) 121: printf("EOH\n"); 122: # endif DEBUG 123: 124: /* throw away a blank line */ 125: if (buf[0] == '\0') 126: { 127: (void) sfgets(buf, MAXFIELD, InChannel); 128: fixcrlf(buf, TRUE); 129: } 130: 131: /* 132: ** Collect the body of the message. 133: */ 134: 135: for (; !feof(InChannel); !feof(InChannel) && !ferror(InChannel) && 136: sfgets(buf, sizeof buf, InChannel) != NULL) 137: { 138: register char *bp = buf; 139: 140: fixcrlf(buf, TRUE); 141: 142: /* check for end-of-message */ 143: if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0')) 144: break; 145: 146: /* check for transparent dot */ 147: if (OpMode == MD_SMTP && !IgnrDot && bp[0] == '.' && bp[1] == '.') 148: bp++; 149: 150: /* 151: ** Figure message length, output the line to the temp 152: ** file, and insert a newline if missing. 153: */ 154: 155: CurEnv->e_msgsize += strlen(bp) + 1; 156: fputs(bp, tf); 157: fputs("\n", tf); 158: if (ferror(tf)) 159: tferror(tf); 160: } 161: if (fflush(tf) != 0) 162: tferror(tf); 163: (void) fclose(tf); 164: 165: /* An EOF when running SMTP is an error */ 166: if (feof(InChannel) && OpMode == MD_SMTP) 167: syserr("collect: unexpected close"); 168: 169: /* 170: ** Find out some information from the headers. 171: ** Examples are who is the from person & the date. 172: */ 173: 174: eatheader(CurEnv); 175: 176: /* 177: ** Add an Apparently-To: line if we have no recipient lines. 178: */ 179: 180: if (hvalue("to") == NULL && hvalue("cc") == NULL && 181: hvalue("bcc") == NULL && hvalue("apparently-to") == NULL) 182: { 183: register ADDRESS *q; 184: 185: /* create an Apparently-To: field */ 186: /* that or reject the message.... */ 187: for (q = CurEnv->e_sendqueue; q != NULL; q = q->q_next) 188: { 189: if (q->q_alias != NULL) 190: continue; 191: # ifdef DEBUG 192: if (tTd(30, 3)) 193: printf("Adding Apparently-To: %s\n", q->q_paddr); 194: # endif DEBUG 195: addheader("apparently-to", q->q_paddr, CurEnv); 196: } 197: } 198: 199: if ((CurEnv->e_dfp = fopen(CurEnv->e_df, "r")) == NULL) 200: syserr("Cannot reopen %s", CurEnv->e_df); 201: } 202: /* 203: ** TFERROR -- signal error on writing the temporary file. 204: ** 205: ** Parameters: 206: ** tf -- the file pointer for the temporary file. 207: ** 208: ** Returns: 209: ** none. 210: ** 211: ** Side Effects: 212: ** Gives an error message. 213: ** Arranges for following output to go elsewhere. 214: */ 215: 216: tferror(tf) 217: FILE *tf; 218: { 219: if (errno == ENOSPC) 220: { 221: (void) freopen(CurEnv->e_df, "w", tf); 222: fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf); 223: usrerr("452 Out of disk space for temp file"); 224: } 225: else 226: syserr("collect: Cannot write %s", CurEnv->e_df); 227: (void) freopen("/dev/null", "w", tf); 228: } 229: /* 230: ** EATFROM -- chew up a UNIX style from line and process 231: ** 232: ** This does indeed make some assumptions about the format 233: ** of UNIX messages. 234: ** 235: ** Parameters: 236: ** fm -- the from line. 237: ** 238: ** Returns: 239: ** none. 240: ** 241: ** Side Effects: 242: ** extracts what information it can from the header, 243: ** such as the date. 244: */ 245: 246: # ifndef NOTUNIX 247: 248: char *DowList[] = 249: { 250: "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL 251: }; 252: 253: char *MonthList[] = 254: { 255: "Jan", "Feb", "Mar", "Apr", "May", "Jun", 256: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 257: NULL 258: }; 259: 260: eatfrom(fm) 261: char *fm; 262: { 263: register char *p; 264: register char **dt; 265: 266: # ifdef DEBUG 267: if (tTd(30, 2)) 268: printf("eatfrom(%s)\n", fm); 269: # endif DEBUG 270: 271: /* find the date part */ 272: p = fm; 273: while (*p != '\0') 274: { 275: /* skip a word */ 276: while (*p != '\0' && *p != ' ') 277: *p++; 278: while (*p == ' ') 279: *p++; 280: if (!isupper(*p) || p[3] != ' ' || p[13] != ':' || p[16] != ':') 281: continue; 282: 283: /* we have a possible date */ 284: for (dt = DowList; *dt != NULL; dt++) 285: if (strncmp(*dt, p, 3) == 0) 286: break; 287: if (*dt == NULL) 288: continue; 289: 290: for (dt = MonthList; *dt != NULL; dt++) 291: if (strncmp(*dt, &p[4], 3) == 0) 292: break; 293: if (*dt != NULL) 294: break; 295: } 296: 297: if (*p != NULL) 298: { 299: char *q; 300: extern char *arpadate(); 301: 302: /* we have found a date */ 303: q = xalloc(25); 304: strncpy(q, p, 25); 305: q[24] = '\0'; 306: define('d', q, CurEnv); 307: q = arpadate(q); 308: define('a', newstr(q), CurEnv); 309: } 310: } 311: 312: # endif NOTUNIX