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