📄 envelope.c
字号:
/* * Copyright (c) 1983 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)envelope.c 8.34 (Berkeley) 4/14/94";#endif /* not lint */#include "sendmail.h"#include <pwd.h>/*** NEWENVELOPE -- allocate a new envelope**** Supports inheritance.**** Parameters:** e -- the new envelope to fill in.** parent -- the envelope to be the parent of e.**** Returns:** e.**** Side Effects:** none.*/ENVELOPE *newenvelope(e, parent) register ENVELOPE *e; register ENVELOPE *parent;{ extern putheader(), putbody(); extern ENVELOPE BlankEnvelope; if (e == parent && e->e_parent != NULL) parent = e->e_parent; clearenvelope(e, TRUE); if (e == CurEnv) bcopy((char *) &NullAddress, (char *) &e->e_from, sizeof e->e_from); else bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from); e->e_parent = parent; e->e_ctime = curtime(); if (parent != NULL) e->e_msgpriority = parent->e_msgsize; e->e_puthdr = putheader; e->e_putbody = putbody; if (CurEnv->e_xfp != NULL) (void) fflush(CurEnv->e_xfp); return (e);}/*** DROPENVELOPE -- deallocate an envelope.**** Parameters:** e -- the envelope to deallocate.**** Returns:** none.**** Side Effects:** housekeeping necessary to dispose of an envelope.** Unlocks this queue file.*/voiddropenvelope(e) register ENVELOPE *e;{ bool queueit = FALSE; bool saveit = bitset(EF_FATALERRS, e->e_flags); register ADDRESS *q; char *id = e->e_id; char buf[MAXLINE]; if (tTd(50, 1)) { printf("dropenvelope %x: id=", e); xputs(e->e_id); printf(", flags=0x%x\n", e->e_flags); if (tTd(50, 10)) { printf("sendq="); printaddr(e->e_sendqueue, TRUE); } } /* we must have an id to remove disk files */ if (id == NULL) return;#ifdef LOG if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags)) logsender(e, NULL); if (LogLevel > 84) syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=0x%x, pid=%d", id, e->e_flags, getpid());#endif /* LOG */ e->e_flags &= ~EF_LOGSENDER; /* post statistics */ poststats(StatFile); /* ** Extract state information from dregs of send list. */ e->e_flags &= ~EF_QUEUERUN; for (q = e->e_sendqueue; q != NULL; q = q->q_next) { if (bitset(QQUEUEUP, q->q_flags)) queueit = TRUE; if (!bitset(QDONTSEND, q->q_flags) && bitset(QBADADDR, q->q_flags)) { if (q->q_owner == NULL && strcmp(e->e_from.q_paddr, "<>") != 0) (void) sendtolist(e->e_from.q_paddr, NULL, &e->e_errorqueue, e); } } /* ** See if the message timed out. */ if (!queueit) /* nothing to do */ ; else if (curtime() > e->e_ctime + TimeOuts.to_q_return) { (void) sprintf(buf, "Cannot send message for %s", pintvl(TimeOuts.to_q_return, FALSE)); if (e->e_message != NULL) free(e->e_message); e->e_message = newstr(buf); message(buf); e->e_flags |= EF_CLRQUEUE; saveit = TRUE; fprintf(e->e_xfp, "Message could not be delivered for %s\n", pintvl(TimeOuts.to_q_return, FALSE)); fprintf(e->e_xfp, "Message will be deleted from queue\n"); for (q = e->e_sendqueue; q != NULL; q = q->q_next) { if (bitset(QQUEUEUP, q->q_flags)) q->q_flags |= QBADADDR; } } else if (TimeOuts.to_q_warning > 0 && curtime() > e->e_ctime + TimeOuts.to_q_warning) { if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) && e->e_class >= 0 && strcmp(e->e_from.q_paddr, "<>") != 0) { (void) sprintf(buf, "warning: cannot send message for %s", pintvl(TimeOuts.to_q_warning, FALSE)); if (e->e_message != NULL) free(e->e_message); e->e_message = newstr(buf); message(buf); e->e_flags |= EF_WARNING; saveit = TRUE; } fprintf(e->e_xfp, "Warning: message still undelivered after %s\n", pintvl(TimeOuts.to_q_warning, FALSE)); fprintf(e->e_xfp, "Will keep trying until message is %s old\n", pintvl(TimeOuts.to_q_return, FALSE)); for (q = e->e_sendqueue; q != NULL; q = q->q_next) { if (bitset(QQUEUEUP, q->q_flags)) q->q_flags |= QREPORT; } } /* ** Send back return receipts as requested. */ if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags) && !bitset(PRIV_NORECEIPTS, PrivacyFlags)) { auto ADDRESS *rlist = NULL; (void) sendtolist(e->e_receiptto, NULLADDR, &rlist, e); (void) returntosender("Return receipt", rlist, FALSE, e); e->e_flags &= ~EF_SENDRECEIPT; } /* ** Arrange to send error messages if there are fatal errors. */ if (saveit && e->e_errormode != EM_QUIET) savemail(e); /* ** Arrange to send warning messages to postmaster as requested. */ if (bitset(EF_PM_NOTIFY, e->e_flags) && PostMasterCopy != NULL && !bitset(EF_RESPONSE, e->e_flags) && e->e_class >= 0) { auto ADDRESS *rlist = NULL; (void) sendtolist(PostMasterCopy, NULLADDR, &rlist, e); (void) returntosender(e->e_message, rlist, FALSE, e); } /* ** Instantiate or deinstantiate the queue. */ if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) || bitset(EF_CLRQUEUE, e->e_flags)) { if (tTd(50, 1)) printf("\n===== Dropping [dq]f%s =====\n\n", e->e_id); if (e->e_df != NULL) xunlink(e->e_df); xunlink(queuename(e, 'q'));#ifdef LOG if (LogLevel > 10) syslog(LOG_INFO, "%s: done", id);#endif } else if (queueit || !bitset(EF_INQUEUE, e->e_flags)) {#ifdef QUEUE queueup(e, bitset(EF_KEEPQUEUE, e->e_flags), FALSE);#else /* QUEUE */ syserr("554 dropenvelope: queueup");#endif /* QUEUE */ } /* now unlock the job */ closexscript(e); unlockqueue(e); /* make sure that this envelope is marked unused */ if (e->e_dfp != NULL) (void) xfclose(e->e_dfp, "dropenvelope", e->e_df); e->e_dfp = NULL; e->e_id = e->e_df = NULL;}/*** CLEARENVELOPE -- clear an envelope without unlocking**** This is normally used by a child process to get a clean** envelope without disturbing the parent.**** Parameters:** e -- the envelope to clear.** fullclear - if set, the current envelope is total** garbage and should be ignored; otherwise,** release any resources it may indicate.**** Returns:** none.**** Side Effects:** Closes files associated with the envelope.** Marks the envelope as unallocated.*/voidclearenvelope(e, fullclear) register ENVELOPE *e; bool fullclear;{ register HDR *bh; register HDR **nhp; extern ENVELOPE BlankEnvelope; if (!fullclear) { /* clear out any file information */ if (e->e_xfp != NULL) (void) xfclose(e->e_xfp, "clearenvelope xfp", e->e_id); if (e->e_dfp != NULL) (void) xfclose(e->e_dfp, "clearenvelope dfp", e->e_df); e->e_xfp = e->e_dfp = NULL; } /* now clear out the data */ STRUCTCOPY(BlankEnvelope, *e); if (Verbose) e->e_sendmode = SM_DELIVER; bh = BlankEnvelope.e_header; nhp = &e->e_header; while (bh != NULL) { *nhp = (HDR *) xalloc(sizeof *bh); bcopy((char *) bh, (char *) *nhp, sizeof *bh); bh = bh->h_link; nhp = &(*nhp)->h_link; }}/*** INITSYS -- initialize instantiation of system**** In Daemon mode, this is done in the child.**** Parameters:** none.**** Returns:** none.**** Side Effects:** Initializes the system macros, some global variables,** etc. In particular, the current time in various** forms is set.*/voidinitsys(e) register ENVELOPE *e;{ char cbuf[5]; /* holds hop count */ char pbuf[10]; /* holds pid */#ifdef TTYNAME static char ybuf[60]; /* holds tty id */ register char *p;#endif /* TTYNAME */ extern char *ttyname(); extern void settime(); extern char Version[]; /* ** Give this envelope a reality. ** I.e., an id, a transcript, and a creation time. */ openxscript(e); e->e_ctime = curtime(); /* ** Set OutChannel to something useful if stdout isn't it. ** This arranges that any extra stuff the mailer produces ** gets sent back to the user on error (because it is ** tucked away in the transcript). */ if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) && e->e_xfp != NULL) OutChannel = e->e_xfp; /* ** Set up some basic system macros. */ /* process id */ (void) sprintf(pbuf, "%d", getpid()); define('p', newstr(pbuf), e);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -