1c2aa98e2SPeter Wemm /* 206f25ae9SGregory Neil Shapiro * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. 306f25ae9SGregory Neil Shapiro * All rights reserved. 4c2aa98e2SPeter Wemm * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5c2aa98e2SPeter Wemm * Copyright (c) 1988, 1993 6c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 7c2aa98e2SPeter Wemm * 8c2aa98e2SPeter Wemm * By using this file, you agree to the terms and conditions set 9c2aa98e2SPeter Wemm * forth in the LICENSE file which can be found at the top level of 10c2aa98e2SPeter Wemm * the sendmail distribution. 11c2aa98e2SPeter Wemm * 12c2aa98e2SPeter Wemm */ 13c2aa98e2SPeter Wemm 14c2aa98e2SPeter Wemm #ifndef lint 1506f25ae9SGregory Neil Shapiro static char id[] = "@(#)$Id: collect.c,v 8.136.4.3 2000/06/22 22:13:45 geir Exp $"; 1606f25ae9SGregory Neil Shapiro #endif /* ! lint */ 17c2aa98e2SPeter Wemm 1806f25ae9SGregory Neil Shapiro #include <sendmail.h> 19c2aa98e2SPeter Wemm 2006f25ae9SGregory Neil Shapiro 2106f25ae9SGregory Neil Shapiro static void collecttimeout __P((time_t)); 2206f25ae9SGregory Neil Shapiro static void dferror __P((FILE *volatile, char *, ENVELOPE *)); 2306f25ae9SGregory Neil Shapiro static void eatfrom __P((char *volatile, ENVELOPE *)); 2406f25ae9SGregory Neil Shapiro 2506f25ae9SGregory Neil Shapiro /* 26c2aa98e2SPeter Wemm ** COLLECT -- read & parse message header & make temp file. 27c2aa98e2SPeter Wemm ** 28c2aa98e2SPeter Wemm ** Creates a temporary file name and copies the standard 29c2aa98e2SPeter Wemm ** input to that file. Leading UNIX-style "From" lines are 30c2aa98e2SPeter Wemm ** stripped off (after important information is extracted). 31c2aa98e2SPeter Wemm ** 32c2aa98e2SPeter Wemm ** Parameters: 33c2aa98e2SPeter Wemm ** fp -- file to read. 34c2aa98e2SPeter Wemm ** smtpmode -- if set, we are running SMTP: give an RFC821 35c2aa98e2SPeter Wemm ** style message to say we are ready to collect 36c2aa98e2SPeter Wemm ** input, and never ignore a single dot to mean 37c2aa98e2SPeter Wemm ** end of message. 38c2aa98e2SPeter Wemm ** hdrp -- the location to stash the header. 39c2aa98e2SPeter Wemm ** e -- the current envelope. 40c2aa98e2SPeter Wemm ** 41c2aa98e2SPeter Wemm ** Returns: 42c2aa98e2SPeter Wemm ** none. 43c2aa98e2SPeter Wemm ** 44c2aa98e2SPeter Wemm ** Side Effects: 45c2aa98e2SPeter Wemm ** Temp file is created and filled. 46c2aa98e2SPeter Wemm ** The from person may be set. 47c2aa98e2SPeter Wemm */ 48c2aa98e2SPeter Wemm 49c2aa98e2SPeter Wemm static jmp_buf CtxCollectTimeout; 50c2aa98e2SPeter Wemm static bool CollectProgress; 51c2aa98e2SPeter Wemm static EVENT *CollectTimeout; 52c2aa98e2SPeter Wemm 53c2aa98e2SPeter Wemm /* values for input state machine */ 54c2aa98e2SPeter Wemm #define IS_NORM 0 /* middle of line */ 55c2aa98e2SPeter Wemm #define IS_BOL 1 /* beginning of line */ 56c2aa98e2SPeter Wemm #define IS_DOT 2 /* read a dot at beginning of line */ 57c2aa98e2SPeter Wemm #define IS_DOTCR 3 /* read ".\r" at beginning of line */ 58c2aa98e2SPeter Wemm #define IS_CR 4 /* read a carriage return */ 59c2aa98e2SPeter Wemm 60c2aa98e2SPeter Wemm /* values for message state machine */ 61c2aa98e2SPeter Wemm #define MS_UFROM 0 /* reading Unix from line */ 62c2aa98e2SPeter Wemm #define MS_HEADER 1 /* reading message header */ 63c2aa98e2SPeter Wemm #define MS_BODY 2 /* reading message body */ 6425bab6e9SPeter Wemm #define MS_DISCARD 3 /* discarding rest of message */ 65c2aa98e2SPeter Wemm 66c2aa98e2SPeter Wemm void 67c2aa98e2SPeter Wemm collect(fp, smtpmode, hdrp, e) 68c2aa98e2SPeter Wemm FILE *fp; 69c2aa98e2SPeter Wemm bool smtpmode; 70c2aa98e2SPeter Wemm HDR **hdrp; 71c2aa98e2SPeter Wemm register ENVELOPE *e; 72c2aa98e2SPeter Wemm { 7306f25ae9SGregory Neil Shapiro register FILE *volatile df; 74c2aa98e2SPeter Wemm volatile bool ignrdot = smtpmode ? FALSE : IgnrDot; 75c2aa98e2SPeter Wemm volatile time_t dbto = smtpmode ? TimeOuts.to_datablock : 0; 76c2aa98e2SPeter Wemm register char *volatile bp; 77c2aa98e2SPeter Wemm volatile int c = EOF; 78c2aa98e2SPeter Wemm volatile bool inputerr = FALSE; 79c2aa98e2SPeter Wemm bool headeronly; 80c2aa98e2SPeter Wemm char *volatile buf; 81c2aa98e2SPeter Wemm volatile int buflen; 82c2aa98e2SPeter Wemm volatile int istate; 83c2aa98e2SPeter Wemm volatile int mstate; 8406f25ae9SGregory Neil Shapiro volatile int hdrslen = 0; 8506f25ae9SGregory Neil Shapiro volatile int numhdrs = 0; 8606f25ae9SGregory Neil Shapiro volatile int dfd; 8706f25ae9SGregory Neil Shapiro volatile int afd; 8806f25ae9SGregory Neil Shapiro volatile int rstat = EX_OK; 89c2aa98e2SPeter Wemm u_char *volatile pbp; 90c2aa98e2SPeter Wemm u_char peekbuf[8]; 9106f25ae9SGregory Neil Shapiro char hsize[16]; 9206f25ae9SGregory Neil Shapiro char hnum[16]; 9306f25ae9SGregory Neil Shapiro char dfname[MAXPATHLEN]; 94c2aa98e2SPeter Wemm char bufbuf[MAXLINE]; 95c2aa98e2SPeter Wemm 96c2aa98e2SPeter Wemm headeronly = hdrp != NULL; 97c2aa98e2SPeter Wemm 98c2aa98e2SPeter Wemm /* 99c2aa98e2SPeter Wemm ** Create the temp file name and create the file. 100c2aa98e2SPeter Wemm */ 101c2aa98e2SPeter Wemm 102c2aa98e2SPeter Wemm if (!headeronly) 103c2aa98e2SPeter Wemm { 104c2aa98e2SPeter Wemm struct stat stbuf; 105c2aa98e2SPeter Wemm 10606f25ae9SGregory Neil Shapiro (void) strlcpy(dfname, queuename(e, 'd'), sizeof dfname); 10706f25ae9SGregory Neil Shapiro #if _FFR_QUEUE_FILE_MODE 10806f25ae9SGregory Neil Shapiro { 10906f25ae9SGregory Neil Shapiro MODE_T oldumask; 11006f25ae9SGregory Neil Shapiro 11106f25ae9SGregory Neil Shapiro if (bitset(S_IWGRP, QueueFileMode)) 11206f25ae9SGregory Neil Shapiro oldumask = umask(002); 11306f25ae9SGregory Neil Shapiro df = bfopen(dfname, QueueFileMode, DataFileBufferSize, 11406f25ae9SGregory Neil Shapiro SFF_OPENASROOT); 11506f25ae9SGregory Neil Shapiro if (bitset(S_IWGRP, QueueFileMode)) 11606f25ae9SGregory Neil Shapiro (void) umask(oldumask); 11706f25ae9SGregory Neil Shapiro } 11806f25ae9SGregory Neil Shapiro #else /* _FFR_QUEUE_FILE_MODE */ 11906f25ae9SGregory Neil Shapiro df = bfopen(dfname, FileMode, DataFileBufferSize, 12006f25ae9SGregory Neil Shapiro SFF_OPENASROOT); 12106f25ae9SGregory Neil Shapiro #endif /* _FFR_QUEUE_FILE_MODE */ 12206f25ae9SGregory Neil Shapiro if (df == NULL) 123c2aa98e2SPeter Wemm { 124c2aa98e2SPeter Wemm syserr("Cannot create %s", dfname); 125c2aa98e2SPeter Wemm e->e_flags |= EF_NO_BODY_RETN; 126065a643dSPeter Wemm finis(TRUE, ExitStat); 12706f25ae9SGregory Neil Shapiro /* NOTREACHED */ 128c2aa98e2SPeter Wemm } 12906f25ae9SGregory Neil Shapiro dfd = fileno(df); 13006f25ae9SGregory Neil Shapiro if (dfd < 0 || fstat(dfd, &stbuf) < 0) 131c2aa98e2SPeter Wemm e->e_dfino = -1; 132c2aa98e2SPeter Wemm else 133c2aa98e2SPeter Wemm { 134c2aa98e2SPeter Wemm e->e_dfdev = stbuf.st_dev; 135c2aa98e2SPeter Wemm e->e_dfino = stbuf.st_ino; 136c2aa98e2SPeter Wemm } 137c2aa98e2SPeter Wemm HasEightBits = FALSE; 138c2aa98e2SPeter Wemm e->e_msgsize = 0; 139c2aa98e2SPeter Wemm e->e_flags |= EF_HAS_DF; 140c2aa98e2SPeter Wemm } 141c2aa98e2SPeter Wemm 142c2aa98e2SPeter Wemm /* 143c2aa98e2SPeter Wemm ** Tell ARPANET to go ahead. 144c2aa98e2SPeter Wemm */ 145c2aa98e2SPeter Wemm 146c2aa98e2SPeter Wemm if (smtpmode) 147c2aa98e2SPeter Wemm message("354 Enter mail, end with \".\" on a line by itself"); 148c2aa98e2SPeter Wemm 149c2aa98e2SPeter Wemm if (tTd(30, 2)) 15006f25ae9SGregory Neil Shapiro dprintf("collect\n"); 151c2aa98e2SPeter Wemm 152c2aa98e2SPeter Wemm /* 153c2aa98e2SPeter Wemm ** Read the message. 154c2aa98e2SPeter Wemm ** 155c2aa98e2SPeter Wemm ** This is done using two interleaved state machines. 156c2aa98e2SPeter Wemm ** The input state machine is looking for things like 157c2aa98e2SPeter Wemm ** hidden dots; the message state machine is handling 158c2aa98e2SPeter Wemm ** the larger picture (e.g., header versus body). 159c2aa98e2SPeter Wemm */ 160c2aa98e2SPeter Wemm 161c2aa98e2SPeter Wemm buf = bp = bufbuf; 162c2aa98e2SPeter Wemm buflen = sizeof bufbuf; 163c2aa98e2SPeter Wemm pbp = peekbuf; 164c2aa98e2SPeter Wemm istate = IS_BOL; 165c2aa98e2SPeter Wemm mstate = SaveFrom ? MS_HEADER : MS_UFROM; 166c2aa98e2SPeter Wemm CollectProgress = FALSE; 167c2aa98e2SPeter Wemm 168c2aa98e2SPeter Wemm if (dbto != 0) 169c2aa98e2SPeter Wemm { 170c2aa98e2SPeter Wemm /* handle possible input timeout */ 171c2aa98e2SPeter Wemm if (setjmp(CtxCollectTimeout) != 0) 172c2aa98e2SPeter Wemm { 173c2aa98e2SPeter Wemm if (LogLevel > 2) 174c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, e->e_id, 175c2aa98e2SPeter Wemm "timeout waiting for input from %s during message collect", 176c2aa98e2SPeter Wemm CurHostName ? CurHostName : "<local machine>"); 177c2aa98e2SPeter Wemm errno = 0; 17806f25ae9SGregory Neil Shapiro usrerr("451 4.4.1 timeout waiting for input during message collect"); 179c2aa98e2SPeter Wemm goto readerr; 180c2aa98e2SPeter Wemm } 181c2aa98e2SPeter Wemm CollectTimeout = setevent(dbto, collecttimeout, dbto); 182c2aa98e2SPeter Wemm } 183c2aa98e2SPeter Wemm 184c2aa98e2SPeter Wemm for (;;) 185c2aa98e2SPeter Wemm { 186c2aa98e2SPeter Wemm if (tTd(30, 35)) 18706f25ae9SGregory Neil Shapiro dprintf("top, istate=%d, mstate=%d\n", istate, mstate); 188c2aa98e2SPeter Wemm for (;;) 189c2aa98e2SPeter Wemm { 190c2aa98e2SPeter Wemm if (pbp > peekbuf) 191c2aa98e2SPeter Wemm c = *--pbp; 192c2aa98e2SPeter Wemm else 193c2aa98e2SPeter Wemm { 194c2aa98e2SPeter Wemm while (!feof(fp) && !ferror(fp)) 195c2aa98e2SPeter Wemm { 196c2aa98e2SPeter Wemm errno = 0; 197c2aa98e2SPeter Wemm c = getc(fp); 198c2aa98e2SPeter Wemm if (errno != EINTR) 199c2aa98e2SPeter Wemm break; 200c2aa98e2SPeter Wemm clearerr(fp); 201c2aa98e2SPeter Wemm } 202c2aa98e2SPeter Wemm CollectProgress = TRUE; 203c2aa98e2SPeter Wemm if (TrafficLogFile != NULL && !headeronly) 204c2aa98e2SPeter Wemm { 205c2aa98e2SPeter Wemm if (istate == IS_BOL) 20606f25ae9SGregory Neil Shapiro (void) fprintf(TrafficLogFile, "%05d <<< ", 207c2aa98e2SPeter Wemm (int) getpid()); 208c2aa98e2SPeter Wemm if (c == EOF) 20906f25ae9SGregory Neil Shapiro (void) fprintf(TrafficLogFile, "[EOF]\n"); 210c2aa98e2SPeter Wemm else 21106f25ae9SGregory Neil Shapiro (void) putc(c, TrafficLogFile); 212c2aa98e2SPeter Wemm } 213c2aa98e2SPeter Wemm if (c == EOF) 214c2aa98e2SPeter Wemm goto readerr; 215c2aa98e2SPeter Wemm if (SevenBitInput) 216c2aa98e2SPeter Wemm c &= 0x7f; 217c2aa98e2SPeter Wemm else 218c2aa98e2SPeter Wemm HasEightBits |= bitset(0x80, c); 219c2aa98e2SPeter Wemm } 220c2aa98e2SPeter Wemm if (tTd(30, 94)) 22106f25ae9SGregory Neil Shapiro dprintf("istate=%d, c=%c (0x%x)\n", 22206f25ae9SGregory Neil Shapiro istate, (char) c, c); 223c2aa98e2SPeter Wemm switch (istate) 224c2aa98e2SPeter Wemm { 225c2aa98e2SPeter Wemm case IS_BOL: 226c2aa98e2SPeter Wemm if (c == '.') 227c2aa98e2SPeter Wemm { 228c2aa98e2SPeter Wemm istate = IS_DOT; 229c2aa98e2SPeter Wemm continue; 230c2aa98e2SPeter Wemm } 231c2aa98e2SPeter Wemm break; 232c2aa98e2SPeter Wemm 233c2aa98e2SPeter Wemm case IS_DOT: 234c2aa98e2SPeter Wemm if (c == '\n' && !ignrdot && 235c2aa98e2SPeter Wemm !bitset(EF_NL_NOT_EOL, e->e_flags)) 236c2aa98e2SPeter Wemm goto readerr; 237c2aa98e2SPeter Wemm else if (c == '\r' && 238c2aa98e2SPeter Wemm !bitset(EF_CRLF_NOT_EOL, e->e_flags)) 239c2aa98e2SPeter Wemm { 240c2aa98e2SPeter Wemm istate = IS_DOTCR; 241c2aa98e2SPeter Wemm continue; 242c2aa98e2SPeter Wemm } 243c2aa98e2SPeter Wemm else if (c != '.' || 244c2aa98e2SPeter Wemm (OpMode != MD_SMTP && 245c2aa98e2SPeter Wemm OpMode != MD_DAEMON && 246c2aa98e2SPeter Wemm OpMode != MD_ARPAFTP)) 247c2aa98e2SPeter Wemm { 248c2aa98e2SPeter Wemm *pbp++ = c; 249c2aa98e2SPeter Wemm c = '.'; 250c2aa98e2SPeter Wemm } 251c2aa98e2SPeter Wemm break; 252c2aa98e2SPeter Wemm 253c2aa98e2SPeter Wemm case IS_DOTCR: 254c2aa98e2SPeter Wemm if (c == '\n' && !ignrdot) 255c2aa98e2SPeter Wemm goto readerr; 256c2aa98e2SPeter Wemm else 257c2aa98e2SPeter Wemm { 258c2aa98e2SPeter Wemm /* push back the ".\rx" */ 259c2aa98e2SPeter Wemm *pbp++ = c; 260c2aa98e2SPeter Wemm *pbp++ = '\r'; 261c2aa98e2SPeter Wemm c = '.'; 262c2aa98e2SPeter Wemm } 263c2aa98e2SPeter Wemm break; 264c2aa98e2SPeter Wemm 265c2aa98e2SPeter Wemm case IS_CR: 266c2aa98e2SPeter Wemm if (c == '\n') 267c2aa98e2SPeter Wemm istate = IS_BOL; 268c2aa98e2SPeter Wemm else 269c2aa98e2SPeter Wemm { 27006f25ae9SGregory Neil Shapiro (void) ungetc(c, fp); 271c2aa98e2SPeter Wemm c = '\r'; 272c2aa98e2SPeter Wemm istate = IS_NORM; 273c2aa98e2SPeter Wemm } 274c2aa98e2SPeter Wemm goto bufferchar; 275c2aa98e2SPeter Wemm } 276c2aa98e2SPeter Wemm 277c2aa98e2SPeter Wemm if (c == '\r' && !bitset(EF_CRLF_NOT_EOL, e->e_flags)) 278c2aa98e2SPeter Wemm { 279c2aa98e2SPeter Wemm istate = IS_CR; 280c2aa98e2SPeter Wemm continue; 281c2aa98e2SPeter Wemm } 282c2aa98e2SPeter Wemm else if (c == '\n' && !bitset(EF_NL_NOT_EOL, e->e_flags)) 283c2aa98e2SPeter Wemm istate = IS_BOL; 284c2aa98e2SPeter Wemm else 285c2aa98e2SPeter Wemm istate = IS_NORM; 286c2aa98e2SPeter Wemm 287c2aa98e2SPeter Wemm bufferchar: 288c2aa98e2SPeter Wemm if (!headeronly) 289c2aa98e2SPeter Wemm e->e_msgsize++; 29025bab6e9SPeter Wemm switch (mstate) 291c2aa98e2SPeter Wemm { 29225bab6e9SPeter Wemm case MS_BODY: 293c2aa98e2SPeter Wemm /* just put the character out */ 294c2aa98e2SPeter Wemm if (MaxMessageSize <= 0 || 295c2aa98e2SPeter Wemm e->e_msgsize <= MaxMessageSize) 29606f25ae9SGregory Neil Shapiro (void) putc(c, df); 29725bab6e9SPeter Wemm 29806f25ae9SGregory Neil Shapiro /* FALLTHROUGH */ 29925bab6e9SPeter Wemm 30025bab6e9SPeter Wemm case MS_DISCARD: 301c2aa98e2SPeter Wemm continue; 302c2aa98e2SPeter Wemm } 303c2aa98e2SPeter Wemm 304c2aa98e2SPeter Wemm /* header -- buffer up */ 305c2aa98e2SPeter Wemm if (bp >= &buf[buflen - 2]) 306c2aa98e2SPeter Wemm { 307c2aa98e2SPeter Wemm char *obuf; 308c2aa98e2SPeter Wemm 309c2aa98e2SPeter Wemm if (mstate != MS_HEADER) 310c2aa98e2SPeter Wemm break; 311c2aa98e2SPeter Wemm 312c2aa98e2SPeter Wemm /* out of space for header */ 313c2aa98e2SPeter Wemm obuf = buf; 314c2aa98e2SPeter Wemm if (buflen < MEMCHUNKSIZE) 315c2aa98e2SPeter Wemm buflen *= 2; 316c2aa98e2SPeter Wemm else 317c2aa98e2SPeter Wemm buflen += MEMCHUNKSIZE; 318c2aa98e2SPeter Wemm buf = xalloc(buflen); 31906f25ae9SGregory Neil Shapiro memmove(buf, obuf, bp - obuf); 320c2aa98e2SPeter Wemm bp = &buf[bp - obuf]; 321c2aa98e2SPeter Wemm if (obuf != bufbuf) 322c2aa98e2SPeter Wemm free(obuf); 323c2aa98e2SPeter Wemm } 324c2aa98e2SPeter Wemm if (c >= 0200 && c <= 0237) 325c2aa98e2SPeter Wemm { 32606f25ae9SGregory Neil Shapiro #if 0 /* causes complaints -- figure out something for 8.11 */ 327c2aa98e2SPeter Wemm usrerr("Illegal character 0x%x in header", c); 32806f25ae9SGregory Neil Shapiro #else /* 0 */ 32906f25ae9SGregory Neil Shapiro /* EMPTY */ 33006f25ae9SGregory Neil Shapiro #endif /* 0 */ 331c2aa98e2SPeter Wemm } 332c2aa98e2SPeter Wemm else if (c != '\0') 33325bab6e9SPeter Wemm { 334c2aa98e2SPeter Wemm *bp++ = c; 3352e43090eSPeter Wemm if (MaxHeadersLength > 0 && 3362e43090eSPeter Wemm ++hdrslen > MaxHeadersLength) 33725bab6e9SPeter Wemm { 33825bab6e9SPeter Wemm sm_syslog(LOG_NOTICE, e->e_id, 3392e43090eSPeter Wemm "headers too large (%d max) from %s during message collect", 3402e43090eSPeter Wemm MaxHeadersLength, 34125bab6e9SPeter Wemm CurHostName != NULL ? CurHostName : "localhost"); 34225bab6e9SPeter Wemm errno = 0; 34325bab6e9SPeter Wemm e->e_flags |= EF_CLRQUEUE; 34425bab6e9SPeter Wemm e->e_status = "5.6.0"; 34506f25ae9SGregory Neil Shapiro usrerrenh(e->e_status, 34606f25ae9SGregory Neil Shapiro "552 Headers too large (%d max)", 3472e43090eSPeter Wemm MaxHeadersLength); 34825bab6e9SPeter Wemm mstate = MS_DISCARD; 34925bab6e9SPeter Wemm } 35025bab6e9SPeter Wemm } 351c2aa98e2SPeter Wemm if (istate == IS_BOL) 352c2aa98e2SPeter Wemm break; 353c2aa98e2SPeter Wemm } 354c2aa98e2SPeter Wemm *bp = '\0'; 355c2aa98e2SPeter Wemm 356c2aa98e2SPeter Wemm nextstate: 357c2aa98e2SPeter Wemm if (tTd(30, 35)) 35806f25ae9SGregory Neil Shapiro dprintf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n", 359c2aa98e2SPeter Wemm istate, mstate, buf); 360c2aa98e2SPeter Wemm switch (mstate) 361c2aa98e2SPeter Wemm { 362c2aa98e2SPeter Wemm case MS_UFROM: 363c2aa98e2SPeter Wemm mstate = MS_HEADER; 364c2aa98e2SPeter Wemm #ifndef NOTUNIX 365c2aa98e2SPeter Wemm if (strncmp(buf, "From ", 5) == 0) 366c2aa98e2SPeter Wemm { 367c2aa98e2SPeter Wemm bp = buf; 368c2aa98e2SPeter Wemm eatfrom(buf, e); 369c2aa98e2SPeter Wemm continue; 370c2aa98e2SPeter Wemm } 37106f25ae9SGregory Neil Shapiro #endif /* ! NOTUNIX */ 37206f25ae9SGregory Neil Shapiro /* FALLTHROUGH */ 373c2aa98e2SPeter Wemm 374c2aa98e2SPeter Wemm case MS_HEADER: 375c2aa98e2SPeter Wemm if (!isheader(buf)) 376c2aa98e2SPeter Wemm { 377c2aa98e2SPeter Wemm mstate = MS_BODY; 378c2aa98e2SPeter Wemm goto nextstate; 379c2aa98e2SPeter Wemm } 380c2aa98e2SPeter Wemm 381c2aa98e2SPeter Wemm /* check for possible continuation line */ 382c2aa98e2SPeter Wemm do 383c2aa98e2SPeter Wemm { 384c2aa98e2SPeter Wemm clearerr(fp); 385c2aa98e2SPeter Wemm errno = 0; 386c2aa98e2SPeter Wemm c = getc(fp); 387c2aa98e2SPeter Wemm } while (errno == EINTR); 388c2aa98e2SPeter Wemm if (c != EOF) 38906f25ae9SGregory Neil Shapiro (void) ungetc(c, fp); 390c2aa98e2SPeter Wemm if (c == ' ' || c == '\t') 391c2aa98e2SPeter Wemm { 392c2aa98e2SPeter Wemm /* yep -- defer this */ 393c2aa98e2SPeter Wemm continue; 394c2aa98e2SPeter Wemm } 395c2aa98e2SPeter Wemm 396c2aa98e2SPeter Wemm /* trim off trailing CRLF or NL */ 397c2aa98e2SPeter Wemm if (*--bp != '\n' || *--bp != '\r') 398c2aa98e2SPeter Wemm bp++; 399c2aa98e2SPeter Wemm *bp = '\0'; 40025bab6e9SPeter Wemm 40106f25ae9SGregory Neil Shapiro if (bitset(H_EOH, chompheader(buf, 40206f25ae9SGregory Neil Shapiro CHHDR_CHECK | CHHDR_USER, 40306f25ae9SGregory Neil Shapiro hdrp, e))) 404c2aa98e2SPeter Wemm { 405c2aa98e2SPeter Wemm mstate = MS_BODY; 406c2aa98e2SPeter Wemm goto nextstate; 407c2aa98e2SPeter Wemm } 40806f25ae9SGregory Neil Shapiro numhdrs++; 409c2aa98e2SPeter Wemm break; 410c2aa98e2SPeter Wemm 411c2aa98e2SPeter Wemm case MS_BODY: 412c2aa98e2SPeter Wemm if (tTd(30, 1)) 41306f25ae9SGregory Neil Shapiro dprintf("EOH\n"); 41406f25ae9SGregory Neil Shapiro 415c2aa98e2SPeter Wemm if (headeronly) 416c2aa98e2SPeter Wemm goto readerr; 41706f25ae9SGregory Neil Shapiro 41806f25ae9SGregory Neil Shapiro /* call the end-of-header check ruleset */ 41906f25ae9SGregory Neil Shapiro snprintf(hnum, sizeof hnum, "%d", numhdrs); 42006f25ae9SGregory Neil Shapiro snprintf(hsize, sizeof hsize, "%d", hdrslen); 42106f25ae9SGregory Neil Shapiro if (tTd(30, 10)) 42206f25ae9SGregory Neil Shapiro dprintf("collect: rscheck(\"check_eoh\", \"%s $| %s\")\n", 42306f25ae9SGregory Neil Shapiro hnum, hsize); 42406f25ae9SGregory Neil Shapiro rstat = rscheck("check_eoh", hnum, hsize, e, FALSE, 42506f25ae9SGregory Neil Shapiro TRUE, 4); 42606f25ae9SGregory Neil Shapiro 427c2aa98e2SPeter Wemm bp = buf; 428c2aa98e2SPeter Wemm 429c2aa98e2SPeter Wemm /* toss blank line */ 430c2aa98e2SPeter Wemm if ((!bitset(EF_CRLF_NOT_EOL, e->e_flags) && 431c2aa98e2SPeter Wemm bp[0] == '\r' && bp[1] == '\n') || 432c2aa98e2SPeter Wemm (!bitset(EF_NL_NOT_EOL, e->e_flags) && 433c2aa98e2SPeter Wemm bp[0] == '\n')) 434c2aa98e2SPeter Wemm { 435c2aa98e2SPeter Wemm break; 436c2aa98e2SPeter Wemm } 437c2aa98e2SPeter Wemm 438c2aa98e2SPeter Wemm /* if not a blank separator, write it out */ 439c2aa98e2SPeter Wemm if (MaxMessageSize <= 0 || 440c2aa98e2SPeter Wemm e->e_msgsize <= MaxMessageSize) 441c2aa98e2SPeter Wemm { 442c2aa98e2SPeter Wemm while (*bp != '\0') 44306f25ae9SGregory Neil Shapiro (void) putc(*bp++, df); 444c2aa98e2SPeter Wemm } 445c2aa98e2SPeter Wemm break; 446c2aa98e2SPeter Wemm } 447c2aa98e2SPeter Wemm bp = buf; 448c2aa98e2SPeter Wemm } 449c2aa98e2SPeter Wemm 450c2aa98e2SPeter Wemm readerr: 451c2aa98e2SPeter Wemm if ((feof(fp) && smtpmode) || ferror(fp)) 452c2aa98e2SPeter Wemm { 453c2aa98e2SPeter Wemm const char *errmsg = errstring(errno); 454c2aa98e2SPeter Wemm 455c2aa98e2SPeter Wemm if (tTd(30, 1)) 45606f25ae9SGregory Neil Shapiro dprintf("collect: premature EOM: %s\n", errmsg); 457c2aa98e2SPeter Wemm if (LogLevel >= 2) 458c2aa98e2SPeter Wemm sm_syslog(LOG_WARNING, e->e_id, 459c2aa98e2SPeter Wemm "collect: premature EOM: %s", errmsg); 460c2aa98e2SPeter Wemm inputerr = TRUE; 461c2aa98e2SPeter Wemm } 462c2aa98e2SPeter Wemm 463c2aa98e2SPeter Wemm /* reset global timer */ 464c2aa98e2SPeter Wemm clrevent(CollectTimeout); 465c2aa98e2SPeter Wemm 466c2aa98e2SPeter Wemm if (headeronly) 467c2aa98e2SPeter Wemm return; 468c2aa98e2SPeter Wemm 46906f25ae9SGregory Neil Shapiro if (df == NULL) 470c2aa98e2SPeter Wemm { 47106f25ae9SGregory Neil Shapiro /* skip next few clauses */ 47206f25ae9SGregory Neil Shapiro /* EMPTY */ 47306f25ae9SGregory Neil Shapiro } 47406f25ae9SGregory Neil Shapiro else if (fflush(df) != 0 || ferror(df)) 47506f25ae9SGregory Neil Shapiro { 47606f25ae9SGregory Neil Shapiro dferror(df, "fflush||ferror", e); 477c2aa98e2SPeter Wemm flush_errors(TRUE); 478065a643dSPeter Wemm finis(TRUE, ExitStat); 47906f25ae9SGregory Neil Shapiro /* NOTREACHED */ 48006f25ae9SGregory Neil Shapiro } 48106f25ae9SGregory Neil Shapiro else if (!SuperSafe) 48206f25ae9SGregory Neil Shapiro { 48306f25ae9SGregory Neil Shapiro /* skip next few clauses */ 48406f25ae9SGregory Neil Shapiro /* EMPTY */ 48506f25ae9SGregory Neil Shapiro } 48606f25ae9SGregory Neil Shapiro else if ((afd = fileno(df)) >= 0 && fsync(afd) < 0) 48706f25ae9SGregory Neil Shapiro { 48806f25ae9SGregory Neil Shapiro dferror(df, "fsync", e); 48906f25ae9SGregory Neil Shapiro flush_errors(TRUE); 49006f25ae9SGregory Neil Shapiro finis(TRUE, ExitStat); 49106f25ae9SGregory Neil Shapiro /* NOTREACHED */ 49206f25ae9SGregory Neil Shapiro } 49306f25ae9SGregory Neil Shapiro else if (bfcommit(df) < 0) 49406f25ae9SGregory Neil Shapiro { 49506f25ae9SGregory Neil Shapiro int save_errno = errno; 49606f25ae9SGregory Neil Shapiro 49706f25ae9SGregory Neil Shapiro if (save_errno == EEXIST) 49806f25ae9SGregory Neil Shapiro { 49906f25ae9SGregory Neil Shapiro char *dfile; 50006f25ae9SGregory Neil Shapiro struct stat st; 50106f25ae9SGregory Neil Shapiro 50206f25ae9SGregory Neil Shapiro dfile = queuename(e, 'd'); 50306f25ae9SGregory Neil Shapiro if (stat(dfile, &st) < 0) 50406f25ae9SGregory Neil Shapiro st.st_size = -1; 50506f25ae9SGregory Neil Shapiro errno = EEXIST; 50606f25ae9SGregory Neil Shapiro syserr("collect: bfcommit(%s): already on disk, size = %ld", 50706f25ae9SGregory Neil Shapiro dfile, st.st_size); 50806f25ae9SGregory Neil Shapiro dfd = fileno(df); 50906f25ae9SGregory Neil Shapiro if (dfd >= 0) 51006f25ae9SGregory Neil Shapiro dumpfd(dfd, TRUE, TRUE); 51106f25ae9SGregory Neil Shapiro } 51206f25ae9SGregory Neil Shapiro errno = save_errno; 51306f25ae9SGregory Neil Shapiro dferror(df, "bfcommit", e); 51406f25ae9SGregory Neil Shapiro flush_errors(TRUE); 51506f25ae9SGregory Neil Shapiro finis(save_errno != EEXIST, ExitStat); 51606f25ae9SGregory Neil Shapiro } 51706f25ae9SGregory Neil Shapiro else if (bfclose(df) < 0) 51806f25ae9SGregory Neil Shapiro { 51906f25ae9SGregory Neil Shapiro dferror(df, "bfclose", e); 52006f25ae9SGregory Neil Shapiro flush_errors(TRUE); 52106f25ae9SGregory Neil Shapiro finis(TRUE, ExitStat); 52206f25ae9SGregory Neil Shapiro /* NOTREACHED */ 52306f25ae9SGregory Neil Shapiro } 52406f25ae9SGregory Neil Shapiro else 52506f25ae9SGregory Neil Shapiro { 52606f25ae9SGregory Neil Shapiro /* everything is happily flushed to disk */ 52706f25ae9SGregory Neil Shapiro df = NULL; 528c2aa98e2SPeter Wemm } 529c2aa98e2SPeter Wemm 530c2aa98e2SPeter Wemm /* An EOF when running SMTP is an error */ 531c2aa98e2SPeter Wemm if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) 532c2aa98e2SPeter Wemm { 533c2aa98e2SPeter Wemm char *host; 534c2aa98e2SPeter Wemm char *problem; 535c2aa98e2SPeter Wemm 536c2aa98e2SPeter Wemm host = RealHostName; 537c2aa98e2SPeter Wemm if (host == NULL) 538c2aa98e2SPeter Wemm host = "localhost"; 539c2aa98e2SPeter Wemm 540c2aa98e2SPeter Wemm if (feof(fp)) 541c2aa98e2SPeter Wemm problem = "unexpected close"; 542c2aa98e2SPeter Wemm else if (ferror(fp)) 543c2aa98e2SPeter Wemm problem = "I/O error"; 544c2aa98e2SPeter Wemm else 545c2aa98e2SPeter Wemm problem = "read timeout"; 546c2aa98e2SPeter Wemm if (LogLevel > 0 && feof(fp)) 547c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, e->e_id, 548c2aa98e2SPeter Wemm "collect: %s on connection from %.100s, sender=%s: %s", 549c2aa98e2SPeter Wemm problem, host, 550c2aa98e2SPeter Wemm shortenstring(e->e_from.q_paddr, MAXSHORTSTR), 551c2aa98e2SPeter Wemm errstring(errno)); 552c2aa98e2SPeter Wemm if (feof(fp)) 55306f25ae9SGregory Neil Shapiro usrerr("451 4.4.1 collect: %s on connection from %s, from=%s", 554c2aa98e2SPeter Wemm problem, host, 555c2aa98e2SPeter Wemm shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); 556c2aa98e2SPeter Wemm else 55706f25ae9SGregory Neil Shapiro syserr("451 4.4.1 collect: %s on connection from %s, from=%s", 558c2aa98e2SPeter Wemm problem, host, 559c2aa98e2SPeter Wemm shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); 560c2aa98e2SPeter Wemm 561c2aa98e2SPeter Wemm /* don't return an error indication */ 562c2aa98e2SPeter Wemm e->e_to = NULL; 563c2aa98e2SPeter Wemm e->e_flags &= ~EF_FATALERRS; 564c2aa98e2SPeter Wemm e->e_flags |= EF_CLRQUEUE; 565c2aa98e2SPeter Wemm 566c2aa98e2SPeter Wemm /* and don't try to deliver the partial message either */ 567c2aa98e2SPeter Wemm if (InChild) 568c2aa98e2SPeter Wemm ExitStat = EX_QUIT; 569065a643dSPeter Wemm finis(TRUE, ExitStat); 57006f25ae9SGregory Neil Shapiro /* NOTREACHED */ 571c2aa98e2SPeter Wemm } 572c2aa98e2SPeter Wemm 573c2aa98e2SPeter Wemm /* 574c2aa98e2SPeter Wemm ** Find out some information from the headers. 575c2aa98e2SPeter Wemm ** Examples are who is the from person & the date. 576c2aa98e2SPeter Wemm */ 577c2aa98e2SPeter Wemm 578c2aa98e2SPeter Wemm eatheader(e, TRUE); 579c2aa98e2SPeter Wemm 580c2aa98e2SPeter Wemm if (GrabTo && e->e_sendqueue == NULL) 581c2aa98e2SPeter Wemm usrerr("No recipient addresses found in header"); 582c2aa98e2SPeter Wemm 583c2aa98e2SPeter Wemm /* collect statistics */ 584c2aa98e2SPeter Wemm if (OpMode != MD_VERIFY) 585c2aa98e2SPeter Wemm markstats(e, (ADDRESS *) NULL, FALSE); 586c2aa98e2SPeter Wemm 587c2aa98e2SPeter Wemm /* 588c2aa98e2SPeter Wemm ** If we have a Return-Receipt-To:, turn it into a DSN. 589c2aa98e2SPeter Wemm */ 590c2aa98e2SPeter Wemm 591c2aa98e2SPeter Wemm if (RrtImpliesDsn && hvalue("return-receipt-to", e->e_header) != NULL) 592c2aa98e2SPeter Wemm { 593c2aa98e2SPeter Wemm ADDRESS *q; 594c2aa98e2SPeter Wemm 595c2aa98e2SPeter Wemm for (q = e->e_sendqueue; q != NULL; q = q->q_next) 596c2aa98e2SPeter Wemm if (!bitset(QHASNOTIFY, q->q_flags)) 597c2aa98e2SPeter Wemm q->q_flags |= QHASNOTIFY|QPINGONSUCCESS; 598c2aa98e2SPeter Wemm } 599c2aa98e2SPeter Wemm 600c2aa98e2SPeter Wemm /* 601c2aa98e2SPeter Wemm ** Add an Apparently-To: line if we have no recipient lines. 602c2aa98e2SPeter Wemm */ 603c2aa98e2SPeter Wemm 604c2aa98e2SPeter Wemm if (hvalue("to", e->e_header) != NULL || 605c2aa98e2SPeter Wemm hvalue("cc", e->e_header) != NULL || 606c2aa98e2SPeter Wemm hvalue("apparently-to", e->e_header) != NULL) 607c2aa98e2SPeter Wemm { 608c2aa98e2SPeter Wemm /* have a valid recipient header -- delete Bcc: headers */ 609c2aa98e2SPeter Wemm e->e_flags |= EF_DELETE_BCC; 610c2aa98e2SPeter Wemm } 611c2aa98e2SPeter Wemm else if (hvalue("bcc", e->e_header) == NULL) 612c2aa98e2SPeter Wemm { 613c2aa98e2SPeter Wemm /* no valid recipient headers */ 614c2aa98e2SPeter Wemm register ADDRESS *q; 615c2aa98e2SPeter Wemm char *hdr = NULL; 616c2aa98e2SPeter Wemm 617c2aa98e2SPeter Wemm /* create an Apparently-To: field */ 618c2aa98e2SPeter Wemm /* that or reject the message.... */ 619c2aa98e2SPeter Wemm switch (NoRecipientAction) 620c2aa98e2SPeter Wemm { 621c2aa98e2SPeter Wemm case NRA_ADD_APPARENTLY_TO: 622c2aa98e2SPeter Wemm hdr = "Apparently-To"; 623c2aa98e2SPeter Wemm break; 624c2aa98e2SPeter Wemm 625c2aa98e2SPeter Wemm case NRA_ADD_TO: 626c2aa98e2SPeter Wemm hdr = "To"; 627c2aa98e2SPeter Wemm break; 628c2aa98e2SPeter Wemm 629c2aa98e2SPeter Wemm case NRA_ADD_BCC: 63006f25ae9SGregory Neil Shapiro addheader("Bcc", " ", 0, &e->e_header); 631c2aa98e2SPeter Wemm break; 632c2aa98e2SPeter Wemm 633c2aa98e2SPeter Wemm case NRA_ADD_TO_UNDISCLOSED: 63406f25ae9SGregory Neil Shapiro addheader("To", "undisclosed-recipients:;", 0, &e->e_header); 635c2aa98e2SPeter Wemm break; 636c2aa98e2SPeter Wemm } 637c2aa98e2SPeter Wemm 638c2aa98e2SPeter Wemm if (hdr != NULL) 639c2aa98e2SPeter Wemm { 640c2aa98e2SPeter Wemm for (q = e->e_sendqueue; q != NULL; q = q->q_next) 641c2aa98e2SPeter Wemm { 642c2aa98e2SPeter Wemm if (q->q_alias != NULL) 643c2aa98e2SPeter Wemm continue; 644c2aa98e2SPeter Wemm if (tTd(30, 3)) 64506f25ae9SGregory Neil Shapiro dprintf("Adding %s: %s\n", 646c2aa98e2SPeter Wemm hdr, q->q_paddr); 64706f25ae9SGregory Neil Shapiro addheader(hdr, q->q_paddr, 0, &e->e_header); 648c2aa98e2SPeter Wemm } 649c2aa98e2SPeter Wemm } 650c2aa98e2SPeter Wemm } 651c2aa98e2SPeter Wemm 652c2aa98e2SPeter Wemm /* check for message too large */ 653c2aa98e2SPeter Wemm if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize) 654c2aa98e2SPeter Wemm { 655c2aa98e2SPeter Wemm e->e_flags |= EF_NO_BODY_RETN|EF_CLRQUEUE; 656c2aa98e2SPeter Wemm e->e_status = "5.2.3"; 65706f25ae9SGregory Neil Shapiro usrerrenh(e->e_status, 65806f25ae9SGregory Neil Shapiro "552 Message exceeds maximum fixed size (%ld)", 659c2aa98e2SPeter Wemm MaxMessageSize); 660c2aa98e2SPeter Wemm if (LogLevel > 6) 661c2aa98e2SPeter Wemm sm_syslog(LOG_NOTICE, e->e_id, 662c2aa98e2SPeter Wemm "message size (%ld) exceeds maximum (%ld)", 663c2aa98e2SPeter Wemm e->e_msgsize, MaxMessageSize); 664c2aa98e2SPeter Wemm } 665c2aa98e2SPeter Wemm 666c2aa98e2SPeter Wemm /* check for illegal 8-bit data */ 667c2aa98e2SPeter Wemm if (HasEightBits) 668c2aa98e2SPeter Wemm { 669c2aa98e2SPeter Wemm e->e_flags |= EF_HAS8BIT; 670c2aa98e2SPeter Wemm if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode) && 671c2aa98e2SPeter Wemm !bitset(EF_IS_MIME, e->e_flags)) 672c2aa98e2SPeter Wemm { 673c2aa98e2SPeter Wemm e->e_status = "5.6.1"; 67406f25ae9SGregory Neil Shapiro usrerrenh(e->e_status, "554 Eight bit data not allowed"); 675c2aa98e2SPeter Wemm } 676c2aa98e2SPeter Wemm } 677c2aa98e2SPeter Wemm else 678c2aa98e2SPeter Wemm { 679c2aa98e2SPeter Wemm /* if it claimed to be 8 bits, well, it lied.... */ 680c2aa98e2SPeter Wemm if (e->e_bodytype != NULL && 681c2aa98e2SPeter Wemm strcasecmp(e->e_bodytype, "8BITMIME") == 0) 682c2aa98e2SPeter Wemm e->e_bodytype = "7BIT"; 683c2aa98e2SPeter Wemm } 684c2aa98e2SPeter Wemm 68506f25ae9SGregory Neil Shapiro if (SuperSafe) 68606f25ae9SGregory Neil Shapiro { 687c2aa98e2SPeter Wemm if ((e->e_dfp = fopen(dfname, "r")) == NULL) 688c2aa98e2SPeter Wemm { 689c2aa98e2SPeter Wemm /* we haven't acked receipt yet, so just chuck this */ 690c2aa98e2SPeter Wemm syserr("Cannot reopen %s", dfname); 691065a643dSPeter Wemm finis(TRUE, ExitStat); 69206f25ae9SGregory Neil Shapiro /* NOTREACHED */ 693c2aa98e2SPeter Wemm } 694c2aa98e2SPeter Wemm } 69506f25ae9SGregory Neil Shapiro else 69606f25ae9SGregory Neil Shapiro e->e_dfp = df; 69706f25ae9SGregory Neil Shapiro if (e->e_dfp == NULL) 69806f25ae9SGregory Neil Shapiro syserr("!collect: no e_dfp"); 69906f25ae9SGregory Neil Shapiro } 700c2aa98e2SPeter Wemm 701c2aa98e2SPeter Wemm 702c2aa98e2SPeter Wemm static void 703c2aa98e2SPeter Wemm collecttimeout(timeout) 704c2aa98e2SPeter Wemm time_t timeout; 705c2aa98e2SPeter Wemm { 706c2aa98e2SPeter Wemm /* if no progress was made, die now */ 707c2aa98e2SPeter Wemm if (!CollectProgress) 708c2aa98e2SPeter Wemm longjmp(CtxCollectTimeout, 1); 709c2aa98e2SPeter Wemm 710c2aa98e2SPeter Wemm /* otherwise reset the timeout */ 711c2aa98e2SPeter Wemm CollectTimeout = setevent(timeout, collecttimeout, timeout); 712c2aa98e2SPeter Wemm CollectProgress = FALSE; 713c2aa98e2SPeter Wemm } 71406f25ae9SGregory Neil Shapiro /* 71506f25ae9SGregory Neil Shapiro ** DFERROR -- signal error on writing the data file. 716c2aa98e2SPeter Wemm ** 717c2aa98e2SPeter Wemm ** Parameters: 71806f25ae9SGregory Neil Shapiro ** df -- the file pointer for the data file. 71906f25ae9SGregory Neil Shapiro ** msg -- detailed message. 720c2aa98e2SPeter Wemm ** e -- the current envelope. 721c2aa98e2SPeter Wemm ** 722c2aa98e2SPeter Wemm ** Returns: 723c2aa98e2SPeter Wemm ** none. 724c2aa98e2SPeter Wemm ** 725c2aa98e2SPeter Wemm ** Side Effects: 726c2aa98e2SPeter Wemm ** Gives an error message. 727c2aa98e2SPeter Wemm ** Arranges for following output to go elsewhere. 728c2aa98e2SPeter Wemm */ 729c2aa98e2SPeter Wemm 73006f25ae9SGregory Neil Shapiro static void 73106f25ae9SGregory Neil Shapiro dferror(df, msg, e) 73206f25ae9SGregory Neil Shapiro FILE *volatile df; 73306f25ae9SGregory Neil Shapiro char *msg; 734c2aa98e2SPeter Wemm register ENVELOPE *e; 735c2aa98e2SPeter Wemm { 73606f25ae9SGregory Neil Shapiro char *dfname; 73706f25ae9SGregory Neil Shapiro 73806f25ae9SGregory Neil Shapiro dfname = queuename(e, 'd'); 739c2aa98e2SPeter Wemm setstat(EX_IOERR); 740c2aa98e2SPeter Wemm if (errno == ENOSPC) 741c2aa98e2SPeter Wemm { 742c2aa98e2SPeter Wemm #if STAT64 > 0 743c2aa98e2SPeter Wemm struct stat64 st; 74406f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */ 745c2aa98e2SPeter Wemm struct stat st; 74606f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */ 747c2aa98e2SPeter Wemm long avail; 748c2aa98e2SPeter Wemm long bsize; 749c2aa98e2SPeter Wemm 750c2aa98e2SPeter Wemm e->e_flags |= EF_NO_BODY_RETN; 751c2aa98e2SPeter Wemm 752c2aa98e2SPeter Wemm if ( 753c2aa98e2SPeter Wemm #if STAT64 > 0 75406f25ae9SGregory Neil Shapiro fstat64(fileno(df), &st) 75506f25ae9SGregory Neil Shapiro #else /* STAT64 > 0 */ 75606f25ae9SGregory Neil Shapiro fstat(fileno(df), &st) 75706f25ae9SGregory Neil Shapiro #endif /* STAT64 > 0 */ 758c2aa98e2SPeter Wemm < 0) 759c2aa98e2SPeter Wemm st.st_size = 0; 76006f25ae9SGregory Neil Shapiro (void) freopen(dfname, "w", df); 761c2aa98e2SPeter Wemm if (st.st_size <= 0) 76206f25ae9SGregory Neil Shapiro fprintf(df, "\n*** Mail could not be accepted"); 76306f25ae9SGregory Neil Shapiro /*CONSTCOND*/ 764c2aa98e2SPeter Wemm else if (sizeof st.st_size > sizeof (long)) 76506f25ae9SGregory Neil Shapiro fprintf(df, "\n*** Mail of at least %s bytes could not be accepted\n", 766c2aa98e2SPeter Wemm quad_to_string(st.st_size)); 767c2aa98e2SPeter Wemm else 76806f25ae9SGregory Neil Shapiro fprintf(df, "\n*** Mail of at least %lu bytes could not be accepted\n", 769c2aa98e2SPeter Wemm (unsigned long) st.st_size); 77006f25ae9SGregory Neil Shapiro fprintf(df, "*** at %s due to lack of disk space for temp file.\n", 771c2aa98e2SPeter Wemm MyHostName); 77206f25ae9SGregory Neil Shapiro avail = freediskspace(qid_printqueue(e->e_queuedir), &bsize); 773c2aa98e2SPeter Wemm if (avail > 0) 774c2aa98e2SPeter Wemm { 775c2aa98e2SPeter Wemm if (bsize > 1024) 776c2aa98e2SPeter Wemm avail *= bsize / 1024; 777c2aa98e2SPeter Wemm else if (bsize < 1024) 778c2aa98e2SPeter Wemm avail /= 1024 / bsize; 77906f25ae9SGregory Neil Shapiro fprintf(df, "*** Currently, %ld kilobytes are available for mail temp files.\n", 780c2aa98e2SPeter Wemm avail); 781c2aa98e2SPeter Wemm } 782c2aa98e2SPeter Wemm e->e_status = "4.3.1"; 78306f25ae9SGregory Neil Shapiro usrerrenh(e->e_status, "452 Out of disk space for temp file"); 784c2aa98e2SPeter Wemm } 785c2aa98e2SPeter Wemm else 78606f25ae9SGregory Neil Shapiro syserr("collect: Cannot write %s (%s, uid=%d)", 78706f25ae9SGregory Neil Shapiro dfname, msg, geteuid()); 78806f25ae9SGregory Neil Shapiro if (freopen("/dev/null", "w", df) == NULL) 789c2aa98e2SPeter Wemm sm_syslog(LOG_ERR, e->e_id, 79006f25ae9SGregory Neil Shapiro "dferror: freopen(\"/dev/null\") failed: %s", 791c2aa98e2SPeter Wemm errstring(errno)); 792c2aa98e2SPeter Wemm } 793c2aa98e2SPeter Wemm /* 794c2aa98e2SPeter Wemm ** EATFROM -- chew up a UNIX style from line and process 795c2aa98e2SPeter Wemm ** 796c2aa98e2SPeter Wemm ** This does indeed make some assumptions about the format 797c2aa98e2SPeter Wemm ** of UNIX messages. 798c2aa98e2SPeter Wemm ** 799c2aa98e2SPeter Wemm ** Parameters: 800c2aa98e2SPeter Wemm ** fm -- the from line. 801c2aa98e2SPeter Wemm ** 802c2aa98e2SPeter Wemm ** Returns: 803c2aa98e2SPeter Wemm ** none. 804c2aa98e2SPeter Wemm ** 805c2aa98e2SPeter Wemm ** Side Effects: 806c2aa98e2SPeter Wemm ** extracts what information it can from the header, 807c2aa98e2SPeter Wemm ** such as the date. 808c2aa98e2SPeter Wemm */ 809c2aa98e2SPeter Wemm 810c2aa98e2SPeter Wemm #ifndef NOTUNIX 811c2aa98e2SPeter Wemm 81206f25ae9SGregory Neil Shapiro static char *DowList[] = 813c2aa98e2SPeter Wemm { 814c2aa98e2SPeter Wemm "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL 815c2aa98e2SPeter Wemm }; 816c2aa98e2SPeter Wemm 81706f25ae9SGregory Neil Shapiro static char *MonthList[] = 818c2aa98e2SPeter Wemm { 819c2aa98e2SPeter Wemm "Jan", "Feb", "Mar", "Apr", "May", "Jun", 820c2aa98e2SPeter Wemm "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 821c2aa98e2SPeter Wemm NULL 822c2aa98e2SPeter Wemm }; 823c2aa98e2SPeter Wemm 82406f25ae9SGregory Neil Shapiro static void 825c2aa98e2SPeter Wemm eatfrom(fm, e) 826c2aa98e2SPeter Wemm char *volatile fm; 827c2aa98e2SPeter Wemm register ENVELOPE *e; 828c2aa98e2SPeter Wemm { 829c2aa98e2SPeter Wemm register char *p; 830c2aa98e2SPeter Wemm register char **dt; 831c2aa98e2SPeter Wemm 832c2aa98e2SPeter Wemm if (tTd(30, 2)) 83306f25ae9SGregory Neil Shapiro dprintf("eatfrom(%s)\n", fm); 834c2aa98e2SPeter Wemm 835c2aa98e2SPeter Wemm /* find the date part */ 836c2aa98e2SPeter Wemm p = fm; 837c2aa98e2SPeter Wemm while (*p != '\0') 838c2aa98e2SPeter Wemm { 839c2aa98e2SPeter Wemm /* skip a word */ 840c2aa98e2SPeter Wemm while (*p != '\0' && *p != ' ') 841c2aa98e2SPeter Wemm p++; 842c2aa98e2SPeter Wemm while (*p == ' ') 843c2aa98e2SPeter Wemm p++; 844c2aa98e2SPeter Wemm if (!(isascii(*p) && isupper(*p)) || 845c2aa98e2SPeter Wemm p[3] != ' ' || p[13] != ':' || p[16] != ':') 846c2aa98e2SPeter Wemm continue; 847c2aa98e2SPeter Wemm 848c2aa98e2SPeter Wemm /* we have a possible date */ 849c2aa98e2SPeter Wemm for (dt = DowList; *dt != NULL; dt++) 850c2aa98e2SPeter Wemm if (strncmp(*dt, p, 3) == 0) 851c2aa98e2SPeter Wemm break; 852c2aa98e2SPeter Wemm if (*dt == NULL) 853c2aa98e2SPeter Wemm continue; 854c2aa98e2SPeter Wemm 855c2aa98e2SPeter Wemm for (dt = MonthList; *dt != NULL; dt++) 856c2aa98e2SPeter Wemm if (strncmp(*dt, &p[4], 3) == 0) 857c2aa98e2SPeter Wemm break; 858c2aa98e2SPeter Wemm if (*dt != NULL) 859c2aa98e2SPeter Wemm break; 860c2aa98e2SPeter Wemm } 861c2aa98e2SPeter Wemm 862c2aa98e2SPeter Wemm if (*p != '\0') 863c2aa98e2SPeter Wemm { 864c2aa98e2SPeter Wemm char *q; 865c2aa98e2SPeter Wemm 866c2aa98e2SPeter Wemm /* we have found a date */ 867c2aa98e2SPeter Wemm q = xalloc(25); 86806f25ae9SGregory Neil Shapiro (void) strlcpy(q, p, 25); 869c2aa98e2SPeter Wemm q = arpadate(q); 870c2aa98e2SPeter Wemm define('a', newstr(q), e); 871c2aa98e2SPeter Wemm } 872c2aa98e2SPeter Wemm } 87306f25ae9SGregory Neil Shapiro #endif /* ! NOTUNIX */ 874