DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T e

⟦b0cab60e5⟧ TextFile

    Length: 18666 (0x48ea)
    Types: TextFile
    Names: »envelope.c,v«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦bfebc70e2⟧ »EurOpenD3/mail/sendmail-5.65b+IDA-1.4.3.tar.Z« 
        └─⟦f9e35cd84⟧ 
            └─⟦this⟧ »sendmail/src/RCS/envelope.c,v« 

TextFile

head	5.22;
branch	5.22.0;
access;
symbols
	UICSO:5.22.0
	VANILLA:5.22;
locks; strict;
comment	@ * @;


5.22
date	90.06.20.08.35.46;	author paul;	state Exp;
branches
	5.22.0.1;
next	;

5.22.0.1
date	90.06.21.13.47.56;	author paul;	state Exp;
branches;
next	5.22.0.2;

5.22.0.2
date	90.07.09.10.18.41;	author paul;	state Exp;
branches;
next	5.22.0.3;

5.22.0.3
date	90.10.16.11.26.36;	author paul;	state Exp;
branches;
next	5.22.0.4;

5.22.0.4
date	90.11.13.14.33.17;	author paul;	state Exp;
branches;
next	5.22.0.5;

5.22.0.5
date	90.11.24.21.45.27;	author paul;	state Exp;
branches;
next	5.22.0.6;

5.22.0.6
date	91.01.19.19.26.02;	author paul;	state Exp;
branches;
next	5.22.0.7;

5.22.0.7
date	91.02.17.04.13.28;	author paul;	state Exp;
branches;
next	5.22.0.8;

5.22.0.8
date	91.03.04.21.48.23;	author paul;	state Exp;
branches;
next	;


desc
@@


5.22
log
@5.64 Berkeley release
@
text
@/*
 * Copyright (c) 1983 Eric P. Allman
 * Copyright (c) 1988 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted provided
 * that: (1) source distributions retain this entire copyright notice and
 * comment, and (2) distributions including binaries display the following
 * acknowledgement:  ``This product includes software developed by the
 * University of California, Berkeley and its contributors'' in the
 * documentation or other materials provided with the distribution and in
 * all advertising materials mentioning features or use of this software.
 * 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
static char sccsid[] = "@@(#)envelope.c	5.22 (Berkeley) 6/1/90";
#endif /* not lint */

#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <pwd.h>
#include <sys/file.h>
#include "sendmail.h"

/*
**  NEWENVELOPE -- allocate a new envelope
**
**	Supports inheritance.
**
**	Parameters:
**		e -- the new envelope to fill in.
**
**	Returns:
**		e.
**
**	Side Effects:
**		none.
*/

ENVELOPE *
newenvelope(e)
	register ENVELOPE *e;
{
	register ENVELOPE *parent;
	extern putheader(), putbody();
	extern ENVELOPE BlankEnvelope;

	parent = CurEnv;
	if (e == CurEnv)
		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();
	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);
}
\f

/*
**  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.
*/

dropenvelope(e)
	register ENVELOPE *e;
{
	bool queueit = FALSE;
	register ADDRESS *q;

	if (tTd(50, 1))
	{
		printf("dropenvelope %x id=", e);
		xputs(e->e_id);
		printf(" flags=%o\n", e->e_flags);
	}
#ifdef LOG
	if (LogLevel > 10)
		syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=%o, pid=%d",
				  e->e_id == NULL ? "(none)" : e->e_id,
				  e->e_flags, getpid());
#endif LOG

	/* we must have an id to remove disk files */
	if (e->e_id == NULL)
		return;

	/*
	**  Extract state information from dregs of send list.
	*/

	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
	{
		if (bitset(QQUEUEUP, q->q_flags))
			queueit = TRUE;
	}

	/*
	**  Send back return receipts as requested.
	*/

	if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags))
	{
		auto ADDRESS *rlist = NULL;

		sendtolist(CurEnv->e_receiptto, (ADDRESS *) NULL, &rlist);
		(void) returntosender("Return receipt", rlist, FALSE);
	}

	/*
	**  Arrange to send error messages if there are fatal errors.
	*/

	if (bitset(EF_FATALERRS|EF_TIMEOUT, e->e_flags) && ErrorMode != EM_QUIET)
		savemail(e);

	/*
	**  Instantiate or deinstantiate the queue.
	*/

	if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) ||
	    bitset(EF_CLRQUEUE, e->e_flags))
	{
		if (e->e_df != NULL)
			xunlink(e->e_df);
		xunlink(queuename(e, 'q'));
	}
	else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
	{
#ifdef QUEUE
		FILE *lockfp, *queueup();
		lockfp = queueup(e, FALSE, FALSE);
		if (lockfp != NULL)
			(void) fclose(lockfp);
#else QUEUE
		syserr("dropenvelope: queueup");
#endif QUEUE
	}

	/* now unlock the job */
	closexscript(e);
	unlockqueue(e);

	/* make sure that this envelope is marked unused */
	e->e_id = e->e_df = NULL;
	if (e->e_dfp != NULL)
		(void) fclose(e->e_dfp);
	e->e_dfp = NULL;
}
\f

/*
**  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.
*/

clearenvelope(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) fclose(e->e_xfp);
		if (e->e_dfp != NULL)
			(void) fclose(e->e_dfp);
	}

	/* now clear out the data */
	STRUCTCOPY(BlankEnvelope, *e);
	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;
	}
}
\f

/*
**  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.
*/

initsys()
{
	static char cbuf[5];			/* holds hop count */
	static char pbuf[10];			/* holds pid */
#ifdef TTYNAME
	static char ybuf[10];			/* holds tty id */
	register char *p;
#endif TTYNAME
	extern char *ttyname();
	extern char *macvalue();
	extern char Version[];

	/*
	**  Give this envelope a reality.
	**	I.e., an id, a transcript, and a creation time.
	*/

	openxscript(CurEnv);
	CurEnv->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 && QueueRun)
		OutChannel = CurEnv->e_xfp;

	/*
	**  Set up some basic system macros.
	*/

	/* process id */
	(void) sprintf(pbuf, "%d", getpid());
	define('p', pbuf, CurEnv);

	/* hop count */
	(void) sprintf(cbuf, "%d", CurEnv->e_hopcount);
	define('c', cbuf, CurEnv);

	/* time as integer, unix time, arpa time */
	settime();

#ifdef TTYNAME
	/* tty name */
	if (macvalue('y', CurEnv) == NULL)
	{
		p = ttyname(2);
		if (p != NULL)
		{
			if (rindex(p, '/') != NULL)
				p = rindex(p, '/') + 1;
			(void) strcpy(ybuf, p);
			define('y', ybuf, CurEnv);
		}
	}
#endif TTYNAME
}
\f

/*
**  SETTIME -- set the current time.
**
**	Parameters:
**		none.
**
**	Returns:
**		none.
**
**	Side Effects:
**		Sets the various time macros -- $a, $b, $d, $t.
*/

settime()
{
	register char *p;
	auto time_t now;
	static char tbuf[20];			/* holds "current" time */
	static char dbuf[30];			/* holds ctime(tbuf) */
	register struct tm *tm;
	extern char *arpadate();
	extern struct tm *gmtime();
	extern char *macvalue();

	now = curtime();
	tm = gmtime(&now);
	(void) sprintf(tbuf, "%02d%02d%02d%02d%02d", tm->tm_year, tm->tm_mon+1,
			tm->tm_mday, tm->tm_hour, tm->tm_min);
	define('t', tbuf, CurEnv);
	(void) strcpy(dbuf, ctime(&now));
	*index(dbuf, '\n') = '\0';
	if (macvalue('d', CurEnv) == NULL)
		define('d', dbuf, CurEnv);
	p = newstr(arpadate(dbuf));
	if (macvalue('a', CurEnv) == NULL)
		define('a', p, CurEnv);
	define('b', p, CurEnv);
}
\f

/*
**  OPENXSCRIPT -- Open transcript file
**
**	Creates a transcript file for possible eventual mailing or
**	sending back.
**
**	Parameters:
**		e -- the envelope to create the transcript in/for.
**
**	Returns:
**		none
**
**	Side Effects:
**		Creates the transcript file.
*/

openxscript(e)
	register ENVELOPE *e;
{
	register char *p;
	int fd;

# ifdef LOG
	if (LogLevel > 19)
		syslog(LOG_DEBUG, "%s: openx%s", e->e_id, e->e_xfp == NULL ? "" : " (no)");
# endif LOG
	if (e->e_xfp != NULL)
		return;
	p = queuename(e, 'x');
	fd = open(p, O_WRONLY|O_CREAT, 0644);
	if (fd < 0)
		syserr("Can't create %s", p);
	else
		e->e_xfp = fdopen(fd, "w");
}
\f

/*
**  CLOSEXSCRIPT -- close the transcript file.
**
**	Parameters:
**		e -- the envelope containing the transcript to close.
**
**	Returns:
**		none.
**
**	Side Effects:
**		none.
*/

closexscript(e)
	register ENVELOPE *e;
{
	if (e->e_xfp == NULL)
		return;
	(void) fclose(e->e_xfp);
	e->e_xfp = NULL;
}
\f

/*
**  SETSENDER -- set the person who this message is from
**
**	Under certain circumstances allow the user to say who
**	s/he is (using -f or -r).  These are:
**	1.  The user's uid is zero (root).
**	2.  The user's login name is in an approved list (typically
**	    from a network server).
**	3.  The address the user is trying to claim has a
**	    "!" character in it (since #2 doesn't do it for
**	    us if we are dialing out for UUCP).
**	A better check to replace #3 would be if the
**	effective uid is "UUCP" -- this would require me
**	to rewrite getpwent to "grab" uucp as it went by,
**	make getname more nasty, do another passwd file
**	scan, or compile the UID of "UUCP" into the code,
**	all of which are reprehensible.
**
**	Assuming all of these fail, we figure out something
**	ourselves.
**
**	Parameters:
**		from -- the person we would like to believe this message
**			is from, as specified on the command line.
**
**	Returns:
**		none.
**
**	Side Effects:
**		sets sendmail's notion of who the from person is.
*/

setsender(from)
	char *from;
{
	register char **pvp;
	char *realname = NULL;
	register struct passwd *pw;
	char buf[MAXNAME];
	char pvpbuf[PSBUFSIZE];
	extern struct passwd *getpwnam();
	extern char *macvalue();
	extern char **prescan();
	extern bool safefile();
	extern char *FullName;

	if (tTd(45, 1))
		printf("setsender(%s)\n", from == NULL ? "" : from);

	/*
	**  Figure out the real user executing us.
	**	Username can return errno != 0 on non-errors.
	*/

	if (QueueRun || OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
		realname = from;
	if (realname == NULL || realname[0] == '\0')
	{
		extern char *username();

		realname = username();
	}

	/*
	**  Determine if this real person is allowed to alias themselves.
	*/

	if (from != NULL)
	{
		extern bool trusteduser();

		if (!trusteduser(realname) && getuid() != geteuid() &&
		    index(from, '!') == NULL && getuid() != 0)
		{
			/* network sends -r regardless (why why why?) */
			/* syserr("%s, you cannot use the -f flag", realname); */
			from = NULL;
		}
	}

	SuprErrs = TRUE;
	if (from == NULL || parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL)
	{
		/* log garbage addresses for traceback */
		if (from != NULL)
		{
# ifdef LOG
			if (LogLevel >= 1)
			    if (realname == from && RealHostName != NULL)
				syslog(LOG_NOTICE,
				    "from=%s unparseable, received from %s",
				    from, RealHostName);
			    else
				syslog(LOG_NOTICE,
				    "Unparseable username %s wants from=%s",
				    realname, from);
# endif LOG
		}
		from = newstr(realname);
		if (parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL &&
		    parseaddr("postmaster", &CurEnv->e_from, 1, '\0') == NULL)
		{
			syserr("setsender: can't even parse postmaster!");
		}
	}
	else
		FromFlag = TRUE;
	CurEnv->e_from.q_flags |= QDONTSEND;
	loweraddr(&CurEnv->e_from);
	SuprErrs = FALSE;

	if (CurEnv->e_from.q_mailer == LocalMailer &&
	    (pw = getpwnam(CurEnv->e_from.q_user)) != NULL)
	{
		/*
		**  Process passwd file entry.
		*/


		/* extract home directory */
		CurEnv->e_from.q_home = newstr(pw->pw_dir);
		define('z', CurEnv->e_from.q_home, CurEnv);

		/* extract user and group id */
		CurEnv->e_from.q_uid = pw->pw_uid;
		CurEnv->e_from.q_gid = pw->pw_gid;

		/* if the user has given fullname already, don't redefine */
		if (FullName == NULL)
			FullName = macvalue('x', CurEnv);
		if (FullName != NULL && FullName[0] == '\0')
			FullName = NULL;

		/* extract full name from passwd file */
		if (FullName == NULL && pw->pw_gecos != NULL &&
		    strcmp(pw->pw_name, CurEnv->e_from.q_user) == 0)
		{
			buildfname(pw->pw_gecos, CurEnv->e_from.q_user, buf);
			if (buf[0] != '\0')
				FullName = newstr(buf);
		}
		if (FullName != NULL)
			define('x', FullName, CurEnv);
	}
	else
	{
		if (CurEnv->e_from.q_home == NULL)
			CurEnv->e_from.q_home = getenv("HOME");
		CurEnv->e_from.q_uid = getuid();
		CurEnv->e_from.q_gid = getgid();
	}

	/*
	**  Rewrite the from person to dispose of possible implicit
	**	links in the net.
	*/

	pvp = prescan(from, '\0', pvpbuf);
	if (pvp == NULL)
	{
# ifdef LOG
		if (LogLevel >= 1)
			syslog(LOG_NOTICE, "cannot prescan from (%s)", from);
# endif
		usrerr("cannot prescan from (%s)", from);
		finis();
	}
	rewrite(pvp, 3);
	rewrite(pvp, 1);
	rewrite(pvp, 4);
	cataddr(pvp, buf, sizeof buf);
	define('f', newstr(buf), CurEnv);

	/* save the domain spec if this mailer wants it */
	if (CurEnv->e_from.q_mailer != NULL &&
	    bitnset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags))
	{
		extern char **copyplist();

		while (*pvp != NULL && strcmp(*pvp, "@@") != 0)
			pvp++;
		if (*pvp != NULL)
			CurEnv->e_fromdomain = copyplist(pvp, TRUE);
	}
}
\f

/*
**  TRUSTEDUSER -- tell us if this user is to be trusted.
**
**	Parameters:
**		user -- the user to be checked.
**
**	Returns:
**		TRUE if the user is in an approved list.
**		FALSE otherwise.
**
**	Side Effects:
**		none.
*/

bool
trusteduser(user)
	char *user;
{
	register char **ulist;
	extern char *TrustedUsers[];

	for (ulist = TrustedUsers; *ulist != NULL; ulist++)
		if (strcmp(*ulist, user) == 0)
			return (TRUE);
	return (FALSE);
}
@


5.22.0.1
log
@Date: Wed, 20 Jun 90 15:39:37 -0400 (EDT)
From: Craig_Everhart@@transarc.com
To: paul@@uxc.cso.uiuc.edu (Paul Pomes - UofIllinois CSO)
Subject: Re: Sendmail V5.64 + IDA enhancements available for anon-FTP

Here's a sendmail patch for you that I've been sending around.  I've
been running it for years, and it was only when Peter Neumann had such
trouble with RISKS duplications that I decided to try to propagate it.

The problem addressed by the fix is that if sendmail delivers to a long
address list (in a single request) but crashes in the middle, it has no
record of the successful deliveries that it has made so far, so when it
eventually gets around to retrying that request, it re-delivers to all
the addresses to which it had been able to deliver earlier.  Not only
does this generate duplicate mail, but the re-delivery process also
requires additional queue processing time, so that it might continue to
take a long time even to attempt delivery to the last address in the
list.

The solution that this patch builds is simple and not very expensive:
after every successful mail delivery, the qf* file is rewritten,
omitting the recipient to whom delivery was successful.  The qf* file
gets shorter even as the request is processed.  A crash in the middle of
processing the list will result in duplicate delivery to at most one
host.  It doesn't require that much time to rewrite the qf* file;
certainly less time than the delivery itself takes.

The only real disadvantage I can imagine is that my sendmail sources
have diverged in many ways from a UCB version of about 1986. 
Nonetheless, it shouldn't be difficult to install this change.

As you can see, this change works by adding an additional flag parameter
to queueup(), then calling queueup() (from sendall()) with this
parameter set sometimes.  The queueup() flag parameter controls which
addresses are rewritten, looking at different flags.

So here's the patch.  I hope that you find it useful.  I look forward to
your reply.

		Thanks,
		Craig Everhart
@
text
@d154 1
a154 1
		lockfp = queueup(e, FALSE, FALSE, FALSE);
@


5.22.0.2
log
@Dropped re-write of queue file due to bug w. too many open files.  This
feature isn't too important for us.
@
text
@d154 1
a154 1
		lockfp = queueup(e, FALSE, FALSE);
@


5.22.0.3
log
@AIX, unlike the rest of the world, does not include time.h with sys/time.h.
@
text
@a26 3
#ifdef _IBMESA
# include <time.h>
#endif /* _IBMESA brain-damage */
@


5.22.0.4
log
@Changed _IBMESA to _AIX (provided in /etc/xlc.cfg).  <sys/file.h> now
included in sendmail.h.
@
text
@d27 1
a27 1
#ifdef _AIX
d29 1
a29 1
#endif /* _AIX brain-damage */
d32 1
@


5.22.0.5
log
@Changed calls to parseaddr() to not pass constant strings.  Commented
out tokens following #else and #endif statements.
@
text
@d106 1
a106 1
#endif /* LOG */
d159 1
a159 1
#else /* !QUEUE */
d161 1
a161 1
#endif /* QUEUE */
d247 1
a247 1
#endif /* TTYNAME */
d298 1
a298 1
#endif /* TTYNAME */
d360 1
a360 1
#ifdef LOG
d363 1
a363 1
#endif /* LOG */
a425 2
static char PostMaster[] = "postmaster";	/* for gcc */

d480 1
a480 1
#ifdef LOG
d490 1
a490 1
#endif /* LOG */
d494 1
a494 1
		    parseaddr(PostMaster, &CurEnv->e_from, 1, '\0') == NULL)
d554 1
a554 1
#ifdef LOG
d557 1
a557 1
#endif /* LOG */
@


5.22.0.6
log
@Deleted #include <sys/types.h> as it's already included via sendmail.h from
useful.h.  #include "sendmail.h" relocated to top of #include list.
@
text
@d25 1
a25 1
#include "sendmail.h"
d32 1
@


5.22.0.7
log
@Added static keyword to declarations for closexscript() and trusteduser().
@
text
@a92 1
	static void closexscript();
a384 1
static void
d464 1
a464 1
		static bool trusteduser();
d594 1
a594 1
static bool
@


5.22.0.8
log
@ANSIfied.
@
text
@a32 8
#ifdef __STDC__
static void closexscript(ENVELOPE *);
static bool trusteduser(const char *);
#else /* !__STDC__ */
static void closexscript();
static bool trusteduser();
#endif /* __STDC__ */

d53 1
a87 1
void
d93 1
d155 1
a155 2
		FILE *lockfp;

a193 1
void
a239 1
void
d249 1
a312 1
void
d320 3
a353 1
void
a428 1
void
d437 4
d454 3
d458 1
d466 2
d574 2
d598 1
a598 1
	const char *user;
@